2014-02-28 13 views
26

Für einen bestimmten Ordner, wie kann ich alle defekten Links darin löschen?Löschen Sie alle unterbrochenen symbolischen Links mit einer Linie?

Ich habe this answer gefunden, die zeigt, wie man einen defekten Link löscht, aber ich kann das nicht in nur einer Zeile zusammenfassen. Gibt es dafür einen One-Liner?

Ein defekter symbolischer Link ist ein Link, der auf eine Datei/Ordner verweist, die nicht mehr existiert.

+0

Gerade von "Mann finden": 'finden -L/usr/ports/packages Typ l exec rm - {} + alle gebrochen symbolische Links löschen in/usr/ports/packages.' –

Antwort

50

Hier ist eine POSIX Weise alle gebrochen symbolische Links im aktuellen Verzeichnis zu löschen , ohne Rekursion. Es funktioniert, indem man find sagt, um symbolische Verbindungen (-L) zu traversieren, aber (-prune) bei jedem Verzeichnis-oder-symbolic-link-to-so zu stoppen.

find -L . -name . -o -type d -prune -o -type l -exec rm {} + 

Sie können auch eine Shell-Schleife verwenden. Der Test -L stimmt mit symbolischen Links überein, und -e stimmt mit vorhandenen Dateien überein (ohne gebrochene symbolische Links).

for x in * .[!.]* ..?*; do if [ -L "$x" ] && ! [ -e "$x" ]; then rm -- "$x"; fi; done 

Wenn Sie in Verzeichnisse rekursiv möchten, diese Technik funktioniert nicht. Mit GNU find (wie auf nicht eingebettetem Linux und Cygwin) können Sie das Prädikat -xtype verwenden, um defekte symbolische Links zu erkennen (-xtype verwendet den Typ des Ziels für symbolische Links und Berichte l für defekte Links).

find -xtype l -delete 

POSIXly, müssen Sie zwei Werkzeuge kombinieren. Sie können find -type l -exec … verwenden, um einen Befehl für jede symbolische Verbindung aufzurufen, und [ -e "$x" ], um zu testen, ob diese Verbindung nicht unterbrochen ist.

find . -type l -exec sh -c 'for x; do [ -e "$x" ] || rm "$x"; done' _ {} + 

Die einfachste Lösung ist die Verwendung von zsh. Um alle gebrochen symbolischen Links im aktuellen Verzeichnis zu löschen:

rm -- *([email protected]) 

Die Zeichen sind in Klammern angegeben glob qualifiers: - zu dereferenzieren Symlinks, @ nur Symlinks entsprechen (die Kombination [email protected] bedeutet gebrochen Symlinks nur) und D zu Punkt übereinstimmen Dateien. Um in Unterverzeichnisse zu rekrutieren, machen Sie das rm -- **/*([email protected]).

+1

+1 für wirklich cool zsh Beispiel und Gesamtantwort. Aber die gleiche Frage: Warum 'rm' und nicht' unlink'? Gibt es Fälle, in denen "rm" nicht sicher ist? – fotanus

+0

@fotanus Uh? Was ist falsch an 'rm'? – Gilles

+0

Ich weiß es nicht, ich frage nur, weil meine Versuchspersonen stattdessen 'unlink' verwenden. Ich weiß nicht warum. Vielleicht weil es ein Link ist? : P jedenfalls, das ist andere Frage – fotanus

0

Sie könnten readlink verwenden, um festzustellen, ob ein Symlink unterbrochen ist oder nicht.

Nachfolgend listet alle gebrochenen Symlinks in einem bestimmten Verzeichnis (und Unterverzeichnisse):

find . -type l -exec sh -c 'readlink -f "{}" 1>/dev/null || echo "{}"' -- "{}" \; 

ersetzen echo mit rm den zerbrochenen loszuwerden!

(Ich habe die Ausgabe von readlink-/dev/null umgeleitet, um Verwirrung zu vermeiden, sondern das Ziel für die Symlinks Liste würde.)

+0

von Ihnen Spitznamen Ich sehe, dass Sie gerne nach/dev/null umleiten :-) Danke, was ist mit 'unlink'? – fotanus

+0

@fotanus Warum 'unlink', was ist das Problem mit' rm'? – devnull

+0

@fotanus BTW, wie erwähnt, in diesem Fall Umleitung auf '/ dev/null 'war rein um Verwirrung zu vermeiden. Selbst wenn Sie das nicht tun und "echo" durch "rm" ersetzen, wird es keinen Nebeneffekt verursachen. – devnull

15

Einfache Antwort basierend auf der Antwort, die Sie (für ein bestimmtes Verzeichnis, $DIR) verknüpft:

find -L $DIR -maxdepth 1 -type l -delete 
+3

Ich mag das Beste. Selbst die Seite zum Finden von Managern scheint zu implizieren, dass dies eine Lösung ist, um gebrochene symbolische Links zu finden. –

+2

Unter Mac OS (BSD 'find') gibt der Befehl von @sanmiguel einen Fehler zurück:' find: -delete: verboten, wenn symlinks verfolgt werden ' – Diti

+0

@Diti: Siehe https://stackoverflow.com/a/45233047/1874627 – saurabheights

3

Von man find Beispielen :

find -L /usr/ports/packages -type l -exec rm -- {} + 

Delete all broken symbolic links in /usr/ports/packages.

1

Das Paket symlinks ist vorinstalliert auf vielen Distributionen (einschließlich Ubuntu 16.04 & Fedora 25) und ein paar wirklich nützliche Features hat, von denen tut genau das, was Sie suchen:

symlinks -d ./ 
+0

Symlinks ist nicht auf CentOS 7.3 oder Ubuntu 14 vorinstalliert. Ubuntu 16 hat Kernel 4.10, die dieses Problem hat: https://groups.google.com/forum/#!topic/linux.kernel/C1Uk5cnrPgs. Wenn Sie keinen SSL-Server betreiben, ist Ubuntu 16 wahrscheinlich in Ordnung. –

0

Für MAC, machen einen Trockenlauf wie folgt: -

DIR=<some path> 
find -L $DIR -maxdepth 1 -type l -print 

Nun können Sie die alten Symlinks beschneiden wie folgt: -

for f in `find -L $DIR -maxdepth 1 -type l`; do unlink $f; done 
0

Sie können versuchen, rmlint zu verwenden.

Zuerst wechseln Sie in den Ordner, der gebrochene Symlinks enthält, und dann die folgenden Befehle laufen nirgendwo zeigen schlechte Symlinks zu finden:

rmlint --types="badlinks" 

Dann rmlint wird ein Bash-Skript rmlint.sh in Ihrem aktuellen erstellen Verzeichnis und drucken Sie eine Liste der schlechten symbolischen Verbindungen in Ihrem Terminal. Um alle schlechten Symlinks in Ihrem aktuellen Verzeichnis zu löschen, können Sie

./rmlint.sh 

Nicht gerade ein Liner laufen, aber es ist sehr einfach zu bedienen.