it-swarm.com.de

Wie finde ich defekte Symlinks?

Gibt es eine Möglichkeit, alle symbolischen Links zu finden, die nicht auf etwas verweisen?

find ./ -type l

gibt mir alle symbolischen Links, macht aber keinen Unterschied zwischen Links, die irgendwohin gehen, und Links, die nicht gehen.

Ich mache gerade:

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

Aber ich frage mich, welche alternativen Lösungen es gibt.

304
gabe.

Ich würde dringend empfehlen , nicht find -L Für die Aufgabe zu verwenden (Erklärung siehe unten). Hier sind einige andere Möglichkeiten, dies zu tun:

  • Wenn Sie eine "pure find" -Methode verwenden möchten, sollte sie eher so aussehen:

    find . -xtype l
    

    (xtype ist ein Test, der an einem dereferenzierten Link durchgeführt wird.) Dies ist möglicherweise nicht in allen Versionen von find verfügbar. obwohl. Es gibt aber auch andere Möglichkeiten:

  • Sie können test -e Auch über den Befehl find ausführen:

    find . -type l ! -exec test -e {} \; -print
    
  • Sogar ein grep Trick könnte besser sein (dh sicherer) als find -L, Aber nicht genau so, wie in der Frage dargestellt (die in ganzen Ausgabezeilen greift) einschließlich Dateinamen):

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

Der find -L Trick zitiert von solo von commandlinef sieht nett und hackig aus, hat aber eine sehr gefährliche Falle : Alle Symlinks werden befolgt. Betrachten Sie das Verzeichnis mit den folgenden Inhalten:

$ 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/

Wenn Sie find -L . -type l In diesem Verzeichnis ausführen, werden auch alle /usr/share/ Gesucht (und das kann sehr lange dauern).1. Verwenden Sie für einen find -Befehl, der "immun gegen ausgehende Links" ist, nicht -L.


1 Dies mag wie eine kleine Unannehmlichkeit aussehen (der Befehl wird "nur" lange dauern, um alle /usr/share Zu durchlaufen) - kann jedoch schwerwiegendere Konsequenzen haben. Betrachten Sie beispielsweise Chroot-Umgebungen: Sie können in einem Unterverzeichnis des Hauptdateisystems vorhanden sein und Symlinks zu absoluten Speicherorten enthalten. Diese Links scheinen für das "äußere" System unterbrochen zu sein, da sie erst dann auf die richtigen Stellen verweisen, wenn Sie die Chroot betreten haben. Ich erinnere mich auch, dass einige Bootloader unter /boot Symlinks verwendeten, die nur in einer anfänglichen Bootphase sinnvoll waren, als die Bootpartition als / Bereitgestellt wurde.

Wenn Sie also einen find -L - Befehl verwenden, um defekte Symlinks zu finden und dann aus einem harmlos aussehenden Verzeichnis zu löschen, können Sie sogar Ihr System beschädigen ...

380
rozcietrzewiacz

Der Befehl symlinks von http://www.ibiblio.org/pub/Linux/utils/file/symlinks-1.4.tar.gz kann verwendet werden, um Symlinks mit einer Sorte zu identifizieren von Eigenschaften. Zum Beispiel:

$ rm a
$ ln -s a b
$ symlinks .
dangling: /tmp/b -> a
41
Sam Morris

Wie rozcietrzewiacz bereits kommentiert hat, find -L kann unerwartete Folgen haben, wenn die Suche in verknüpfte Verzeichnisse erweitert wird. Dies ist also nicht der optimale Ansatz. Was noch niemand erwähnt hat, ist das

find /path/to/search -xtype l

ist der prägnantere und logisch identische Befehl zu

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

Keine der bisher vorgestellten Lösungen erkennt zyklische Symlinks, was eine andere Art von Bruch darstellt. diese Frage befasst sich mit Portabilität. Zusammenfassend lässt sich sagen, dass die tragbare Methode zum Auffinden defekter symbolischer Links, einschließlich zyklischer Links, folgende ist:

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

Weitere Informationen finden Sie unter diese Frage oder ynform.org . Die endgültige Quelle für all dies ist natürlich das findutils documentaton .

33
pooryorick

Ich glaube, das Hinzufügen des -L Flag zu Ihrem Befehl ermöglicht es Ihnen, das grep loszuwerden:

$ find -L . -type l

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

vom Mann:

 -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.
9
kwarrick

Wenn Sie ein anderes Verhalten benötigen, unabhängig davon, ob die Verbindung unterbrochen oder zyklisch ist, können Sie% Y auch mit find verwenden:

$ touch a
$ ln -s a b  # link to existing target
$ ln -s c d  # link to non-existing target
$ ln -s e e  # 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

Dieses Beispiel wurde kopiert von dieser Beitrag (Site gelöscht) .

Referenz

7
andy

Einfache Antwort, die eine Variation der OP-Version darstellt. Manchmal möchten Sie einfach etwas, das sich leicht eingeben oder merken lässt:

find . | xargs file | grep -i "broken symbolic link"

Oder wenn Sie mit NULL-Terminatoren umgehen müssen:

find . -print0 | xargs -0 file | grep -i "broken symbolic link"
3
trinth

Ich benutze dies für meinen Fall und es funktioniert ganz gut, da ich das Verzeichnis kenne, um nach defekten Symlinks zu suchen:

find -L $path -maxdepth 1 -type l

und mein Ordner enthält einen Link zu /usr/share aber es durchquert es nicht. Geräteübergreifende Links und solche, die für Chroots usw. gültig sind, sind immer noch eine Gefahr, aber für meinen Anwendungsfall ist dies ausreichend.

2
Iskren

Für zsh Benutzer:

rm -v **/*([email protected])

von zsh user guide (Suche nach broken symlinks)

2
murlakatamenka

find -L . -type l |xargs symlinks gibt Ihnen pro Foundfile-Basis Auskunft darüber, ob der Link existiert oder nicht.

1
Alex

Dadurch werden die Namen defekter Symlinks im aktuellen Verzeichnis ausgedruckt.

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

Funktioniert in Bash. Ich weiß nichts über andere Muscheln.

1