Wie kann ich alle fest verknüpften Dateien in einem Dateisystem finden?

21

Ich muss alle fest verknüpften Dateien auf einem bestimmten Dateisystem finden. ZB eine Liste von Dateien abrufen, jede Zeile enthält verknüpfte Paare oder Drillinge usw.

Ich verstehe mehr oder weniger, wie es geht, man muss ein Wörterbuch erstellen, das von inode für alle Dateien / Verzeichnisse auf einem Dateisystem verschlüsselt ist, "ausschließen." und ".." links und dann indodes mit mehr als einem namen sind hardlinks ... aber ich hoffe, dass vielleicht eine fertige lösung existiert, oder jemand hat schon so ein script geschrieben.

haimg
quelle

Antworten:

17

Sie können den folgenden Befehl ausführen:

find / -type f -printf '%n %p\n' | awk '$1 > 1{$1="";print}'

um alle fest verlinkten Dateien zu finden.

Oder @mbafford Version:

find / -type f -links +1 -printf '%i %n %p\n'
Gilles Quenot
quelle
1
Danke, das ist nicht genau das, was ich wollte, aber nah genug. Ich kann '% i' hinzufügen, um die Inode-Nummern zu drucken und danach zu sortieren / gruppieren ...
haimg
15
Sie können die Notwendigkeit für awk vermeiden, indem Sie die Syntax "-links + n" von find verwenden. ZB um alle Dateien mit mindestens zwei Links zu finden und die erforderlichen Informationen find / -type f -links +1 -printf '%i %n %p\n'
auszudrucken
Wie wäre es mit einem Piping durch sort(+ uniq)? Ich war neugierig und habe es auf meinem Hauptcomputer ausprobiert (16 GB i5-2500k mit SSD). mit 2187757 files ( find / -xdev -type f | wc) dauert 12 echte Sekunden, wenn 3820 files / 570 inodes ( time sudo find / -xdev -type f -links +1 -printf "%i\n" | sort | uniq | wc) zurückgegeben werden. Sie müssten die %n %pfür die tatsächlichen Dateien enthalten, wie ich sie zum Zählen von Inodes herausnahm.
Northern Bradley
17
find . -type f -links +1 2>/dev/null

gibt eine Liste aller Dateien an, die mehr als einen Link haben, dh Dateien, zu denen ein fester Link existiert. Ein Looping darüber ist dann relativ einfach - eine hackige Lösung, wenn Sie nicht so viele Dateien haben würden

for i in $(find . -type f -links +1 2>/dev/null); do find -samefile $i | awk '{printf "%s ", $1}'; printf "\n"; done | sort | uniq

Aber ich hoffe aufrichtig, dass es bessere Lösungen gibt, zum Beispiel indem Sie zuerst finddie Inode-Nummern drucken lassen und dann die Option von find's verwenden -inum, um alle mit dieser Inode verbundenen Dateien anzuzeigen.

Claudius
quelle
1
Autsch! Dies durchsucht das Dateisystem immer wieder nach jeder fest verknüpften Datei ...
haimg
1
Ich habe nicht behauptet, dass es schnell ist - und es funktioniert für kleine Verzeichnisbäume. Ein richtiger Index, der beispielsweise aus der Ausgabe von erstellt werden könnte find . -type f -printf '%i %p\n', würde es natürlich ermöglichen, eine viel schnellere Lösung zu erstellen.
Claudius
Und das geht nicht mit dem Platz im Pfad AFAIK um.
Gilles Quenot
Für die forSchleife würde eine entsprechende Anpassung von IFS funktionieren. Um die Ausgabe des Befehls find in meinem Kommentar zu analysieren, sollte es auch funktionieren, alles zwischen dem ersten Leerzeichen und dem Ende der Zeile als Dateinamen zu deklarieren.
Claudius
1
@Sati: Stellt sicher, dass Fehlermeldungen verworfen werden (z. B. für Ordner, auf die Sie nicht zugreifen können, lost+foundusw.). Das ist besonders wichtig, wenn die Ausgabe wie in der zweiten Zeile weiterverarbeitet werden soll.
DJCrashdummy
1

IMHO ist der beste Weg, um die folgende Zeile zu verwenden (sicher müssen Sie /PATH/FOR/SEARCH/mit was auch immer Sie suchen , ersetzen ):

find /PATH/FOR/SEARCH/ -xdev -printf '%i\t%n\t%p\n' | fgrep -f <(find . -xdev -printf '%i\n' | sort -n | uniq -d) | sort -n

Dies scannt das Dateisystem nur einmal, zeigt den Inode, die Anzahl der Hardlinks und den Pfad der Dateien mit mehr als einem Hardlink an und sortiert sie nach dem Inode.

Wenn Sie sich über Fehlermeldungen für Ordner ärgern, die Sie nicht lesen dürfen, können Sie die Zeile folgendermaßen erweitern:

find /PATH/FOR/SEARCH/ -xdev -printf '%i\t%n\t%p\n' 2> /dev/null | fgrep -f <(find . -xdev -printf '%i\n' 2> /dev/null | sort -n | uniq -d) | sort -n
DJCrashdummy
quelle