Linux: trouver tous les liens symboliques d'un fichier "original" donné? (reverse 'readlink')

Envisager la suite de la ligne de commande suivante:

$ cd /tmp/
$ mkdir dirA
$ mkdir dirB
$ echo "the contents of the 'original' file" > orig.file
$ ls -la orig.file 
-rw-r--r-- 1 $USER $USER 36 2010-12-26 00:57 orig.file

# create symlinks in dirA and dirB that point to /tmp/orig.file:

$ ln -s $(pwd)/orig.file $(pwd)/dirA/
$ ln -s $(pwd)/orig.file $(pwd)/dirB/lorig.file
$ ls -la dirA/ dirB/
dirA/:
total 44
drwxr-xr-x  2 $USER $USER  4096 2010-12-26 00:57 .
drwxrwxrwt 20 root          root          36864 2010-12-26 00:57 ..
lrwxrwxrwx  1 $USER $USER    14 2010-12-26 00:57 orig.file -> /tmp/orig.file

dirB/:
total 44
drwxr-xr-x  2 $USER $USER  4096 2010-12-26 00:58 .
drwxrwxrwt 20 root          root          36864 2010-12-26 00:57 ..
lrwxrwxrwx  1 $USER $USER    14 2010-12-26 00:58 lorig.file -> /tmp/orig.file

À ce stade, je peux utiliser readlink pour voir ce qu'est le' original '(bien, je suppose que le terme habituel ici est soit' cible 'ou' source', mais ceux dans mon esprit peuvent être des concepts opposés aussi bien, donc je vais juste l'appeler' original') fichier des liens symboliques, i.e.

$ readlink -f dirA/orig.file 
/tmp/orig.file
$ readlink -f dirB/lorig.file 
/tmp/orig.file

... Cependant, ce que je voudrais savoir est - il une commande que je puisse courir sur le fichier, et de trouver tous les liens symboliques qui pointent vers elle? Dans autrement dit, quelque chose comme (pseudo):

$ getsymlinks /tmp/orig.file
/tmp/dirA/orig.file 
/tmp/dirB/lorig.file

Merci d'avance pour vos commentaires,

Cheers!

41
demandé sur Mad Physicist 2010-12-26 03:04:48

6 réponses

Je n'ai pas vu de commande pour cela et ce n'est pas une tâche facile, puisque le fichier cible contient zéro information sur ce que les fichiers source pointent vers lui.

ceci est similaire aux liens "durs" mais au moins ceux-ci sont toujours sur le même système de fichiers donc vous pouvez faire un find -inode pour les énumérer. Les liens mous sont plus problématiques puisqu'ils peuvent croiser des systèmes de fichiers.

je pense que vous allez avoir à faire est fondamentalement effectuer un ls -al sur chaque fichier de votre hiérarchie et utiliser grep rechercher -> /path/to/target/file.

par exemple, en voici un que j'ai lancé sur mon système (formaté pour la lisibilité - ces deux dernières lignes sont en fait sur ligne dans la sortie réelle):

pax$ find / -exec ls -ald {} ';' 2>/dev/null | grep '\-> /usr/share/applications'
lrwxrwxrwx 1 pax pax 23 2010-06-12 14:56 /home/pax/applications_usr_share
                                         -> /usr/share/applications
29
répondu paxdiablo 2010-12-26 00:40:50

utiliser GNU find, ce qui permet de trouver les fichiers qui sont reliés par un lien dur ou symétrique à un fichier:

find -L /dir/to/start -samefile /tmp/orig.file
114
répondu Dennis Williamson 2010-12-26 20:44:25

les liens symboliques ne suivent pas ce qui pointe vers une destination donnée, donc vous ne pouvez pas faire mieux que de vérifier chaque lien symbolique pour voir s'il pointe vers la destination désirée, comme

for i in *; do
    if [ -L "$i" ] && [ "$i" -ef /tmp/orig.file ]; then
        printf "Found: %s\n" "$i"
    fi
done
1
répondu jilles 2010-12-26 00:15:42

Voici ce que j'ai trouvé. Je fais ça sur OS X, qui n'a pas readlink -f, j'ai donc dû utiliser une fonction d'assistance à la remplacer. Si vous avez un bon readlink -f Vous pouvez utiliser cela à la place. Aussi, l'utilisation de while ... done < <(find ...) n'est pas strictement nécessaire dans ce cas, un simple find ... | while ... done fonctionnerait; mais si jamais vous vouliez faire quelque chose comme définir une variable à l'intérieur de la boucle (comme un nombre de fichiers correspondants), la version pipe échouerait parce que le while la boucle fonctionnerait dans un sous-puits. Enfin, notez que j'utilise find ... -type l ainsi la boucle ne s'exécute que sur des liens symboliques, pas sur d'autres types de fichiers.

# Helper function 'cause my system doesn't have readlink -f
readlink-f() {
    orig_dir="$(pwd)"
    f=""
    while [[ -L "$f" ]]; do
        cd "$(dirname "$f")"
        f="$(readlink "$(basename "$f")")"
    done
    cd "$(dirname "$f")"
    printf "%s\n" "$(pwd)/$(basename "$f")"
    cd "$orig_dir"
}

target_file="$(readlink-f "$target_file")" # make sure target is normalized

while IFS= read -d '' linkfile; do
    if [[ "$(readlink-f "$linkfile")" == "$target_file" ]]; then 
        printf "%s\n" "$linkfile"
    fi
done < <(find "$search_dir" -type l -print0)
0
répondu Gordon Davisson 2010-12-26 05:16:44

inspiré par le commentaire de Gordon Davisson. C'est similaire à une autre réponse, mais j'ai obtenu les résultats souhaités en utilisant exec. J'avais besoin de quelque chose qui pouvait trouver des liens symboliques sans savoir où se trouvait le fichier original.

find / -type l -exec ls -al {} \; | grep -i "all_or_part_of_original_name"
0
répondu Jer 2018-04-15 14:18:23

C'est peut-être trop simpliste pour ce que vous voulez faire, mais que je trouve très utile. il ne répond pas à votre question littéralement, car il n'est pas "exécuter sur le fichier original", mais il accomplit la tâche. Mais, beaucoup plus d'accès HDD. Et, il ne fonctionne que pour les fichiers "soft" liés qui est la majorité des fichiers liés utilisateurs.

à partir de la racine de votre répertoire de stockage de données ou des répertoires de données des utilisateurs, où que symlinked "fichiers" à la orig.file peut résider, exécutez la trouver commande:

# find -type l -ls |grep -i 'orig.file' 

ou

# find /Starting/Search\ Path/ -type l -ls |grep -i '*orig*'

J'utiliserais normalement une partie du nom eg,'*orig*' pour commencer, parce que nous savons que les utilisateurs renommer (préfixe) un fichier nommé avec un plus descriptif, les uns comme " Jan rapport de la London _ orig.fichier.2015.01.21 " ou quelque chose.

Note: je N'ai jamais eu l'option-samefile pour travailler pour moi.

propre, simple, facile à retenir

j'espère que cela aidera Quelqu'un. Landis.

-1
répondu Landis Reed 2015-12-20 23:33:22