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!
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
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
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
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)
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"
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.