Comment puis-je find des liens symboliques brisés?

Existe-t-il un moyen de find tous les liens symboliques qui ne pointent pas?

find ./ -type l

me donnera tous les liens symboliques, mais ne fait aucune distinction entre les liens qui vont quelque part et les liens qui ne le font pas.

Je suis en train de faire:

find ./ -type l -exec file {} \; |grep broken

Mais je me request quelles autres solutions existent.

Je suggère fortement de ne pas utiliser find -L pour la tâche (voir ci-dessous pour l'explication). Voici quelques autres façons de le faire:

  • Si vous voulez utiliser une méthode "pure find ", il devrait plutôt ressembler à ceci:

     find . -xtype l 

    ( xtype est un test effectué sur un lien déréférencé) Cela peut ne pas être disponible dans toutes les versions de find , cependant. Mais il y a d'autres options aussi;

  • Vous pouvez également exécuter test -e partir de la command find :

     find . -type l ! -exec test -e {} \; -print 
  • Même un truc de grep pourrait être meilleur (c'est-à-dire plus sûr ) que find -L , mais pas exactement tel que présenté dans la question (qui greps dans les lignes de sortie entières, y compris les noms de files):

      find . -type l -exec sh -c "file -b {} | grep -q ^broken" \; -print 

L'astuce find -L citée en solo par commandlinefu a l' air sympa et hacky, mais elle comporte un piège très dangereux : tous les liens symboliques sont suivis. Considérons le directory avec le contenu présenté ci-dessous:

 $ ls -l total 0 lrwxrwxrwx 1 michal users 6 May 15 08:12 link_1 -> nonexistent1 lrwxrwxrwx 1 michal users 6 May 15 08:13 link_2 -> nonexistent2 lrwxrwxrwx 1 michal users 6 May 15 08:13 link_3 -> nonexistent3 lrwxrwxrwx 1 michal users 6 May 15 08:13 link_4 -> nonexistent4 lrwxrwxrwx 1 michal users 11 May 15 08:20 link_out -> /usr/share/ 

Si vous exécutez find -L . -type l find -L . -type l dans ce directory, tous /usr/share/ serait recherché aussi (et cela peut prendre beaucoup de time) 1 . Pour une command de find "immunisée aux liens sortants", n'utilisez pas -L .


1 Cela peut sembler être un désagrément mineur (la command prendra "juste" du time pour traverser tout /usr/share ), mais peut avoir des conséquences plus graves. Par exemple, considérons les environnements chroot: ils peuvent exister dans un sous-directory du système de files principal et contenir des liens symboliques vers des locations absolus. Ces liens peuvent sembler être cassés pour le système "extérieur", car ils ne font que pointer vers des endroits appropriés une fois que vous êtes entré dans le chroot. Je me souviens aussi que certains bootloaders utilisaient des liens symboliques sous /boot qui n'avaient de sens que dans une phase initiale, quand la partition de démarrage était montée sous / .

Donc, si vous utilisez une command find -L pour find et supprimer des liens symboliques cassés à partir d'un directory inoffensif, vous pourriez même casser votre système …

La command symlinks de http://www.ibiblio.org/pub/Linux/utils/file/symlinks-1.4.tar.gz peut être utilisée pour identifier les liens symboliques avec une variété de caractéristiques. Par exemple:

 $ rm a $ ln -sab $ symlinks . dangling: /tmp/b -> a 

Comme rozcietrzewiacz a déjà commenté, find -L peut avoir des conséquences inattendues d'étendre la search dans les directorys symésortingques, donc l'approche optimale n'est pas. Ce que personne n'a encore mentionné, c'est que

 find /path/to/search -xtype l 

est la command la plus concise et la plus logique

 find /path/to/search -type l -xtype l 

Aucune des solutions présentées jusqu'à présent ne détecte de liens symboliques cycliques, ce qui est un autre type de casse. cette question porte sur la portabilité. Pour résumer, la manière portable de find des liens symboliques brisés, y compris des liens cycliques, est la suivante:

 find /path/to/search -type l -exec test ! -e {} \; -print 

Pour plus de détails, voir cette question ou ynform.org . Bien sûr, la source définitive de tout cela est la documentation findutils .

Je crois que l'ajout du drapeau -L à votre command vous permettra de vous débarrasser du grep:

 $ find -L . -type l 

http://www.commandlinefu.com/commands/view/8260/find-broken-symlinks

de l'homme:

  -L Cause the file information and file type (see stat(2)) returned for each symbolic link to be those of the file referenced by the link, not the link itself. If the referenced file does not exist, the file information and type will be for the link itself. 

Si vous avez besoin d'un comportement différent, que le lien soit cassé ou cyclique, vous pouvez également utiliser% Y avec find:

 $ touch a $ ln -sab # link to existing target $ ln -scd # link to non-existing target $ ln -see # link to itself $ find . -type l -exec test ! -e {} \; -printf '%Y %p\n' \ | while read type link; do case "$type" in N) echo "do something with broken link $link" ;; L) echo "do something with cyclic link $link" ;; esac done do something with broken link ./d do something with cyclic link ./e 

Cet exemple est copié depuis ce post (site supprimé) .

Référence

  • find

find -L . -type l |xargs symlinks find -L . -type l |xargs symlinks vous donnera des informations si le lien existe ou non sur une base foundfile.

Cela imprimera les noms des liens symboliques cassés dans le directory courant.

 for l in $(find . -type l); do cd $(dirname $l); if [ ! -e "$(readlink $(basename $l))" ]; then echo $l; fi; cd - > /dev/null; done 

Travaille à Bash. Je ne sais pas d'autres coquilles.

Je l'utilise pour mon cas et ça marche plutôt bien, car je connais le directory pour searchr des liens symboliques brisés:

 find -L $path -maxdepth 1 -type l 

et mon dossier inclut un lien vers /usr/share mais il ne le traverse pas. Les liens inter-périphériques et ceux qui sont valables pour les chroots, etc. sont toujours un piège mais pour mon cas d'utilisation, c'est suffisant.