Linux: Verzeichnisstruktur vergleichen, ohne Dateien zu vergleichen

53

Was ist die beste und einfachste Möglichkeit, zwei Verzeichnisstrukturen zu vergleichen, ohne die Daten in Dateien zu vergleichen? Das funktioniert gut:

diff -qr dir1 dir2_

Aber es ist wirklich langsam, weil es auch Dateien vergleicht. Gibt es einen Schalter für diff oder ein anderes einfaches cli-Tool, um dies zu tun?

Jonah
quelle
Meinen Sie mit "Verzeichnisstruktur" nur die Verzeichnispfade oder die Pfade sowohl der Verzeichnis- als auch der Nicht-Verzeichnisdateien?
intuited
Ja, Ordner und Dateien.
Jonah
1
In diesem Fall sollten Sie das entfernen -type d Option aus der Antwort von @ slartibartfast, oder checke meine Antwort aus.
intuited

Antworten:

35

Das Folgende (wenn Sie das erste Verzeichnis für Verzeichnis1 und das zweite für Verzeichnis2 einsetzen) sollte schnell und genau das tun, wonach Sie suchen:

find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1

Das Grundprinzip besteht darin, dass alle Verzeichnisse einschließlich der Unterverzeichnispfade relativ zu den Basisverzeichnissen N gedruckt werden.

Dies kann zum Absturz führen (was zu einer seltsamen Ausgabe führt), wenn Sie in einigen Verzeichnisnamen Wagenrückläufe haben, andere jedoch nicht.

Slartibartfast
quelle
Das ist nicht gut für mich, denn wenn ein Verzeichnis einen Ordner mit ein paar tausend Dateien enthält, werden sie alle einzeln aufgelistet, während diff -rq zeigt nur, dass das Stammverzeichnis in einem vorhanden ist, und macht weiter.
Chris Jefferson
Wie Intuited (vor Jahren) hervorhob, sollte zur Beantwortung der OPs-Frage der -Typ d entfernt werden, damit sowohl Dateien als auch Verzeichnisse im Vergleich berücksichtigt werden
user2746401
Ich verstehe und respektiere diese Lektüre der Problemstellung. Das war damals nicht meine Lektüre. Empfehlen Sie, dass ich meine Antwort bearbeite, um auf die aktualisierte Frage zu antworten? Ich mache das in Ordnung, wenn Sie denken, dass es für einige Leute hilfreich ist, und ich lasse die Lösung und die Kommentarsätze in Ordnung, wie sie jetzt sind, was einigermaßen effektiv zu sein scheint.
Slartibartfast
34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

zeigt Ihnen nebeneinander die beiden Verzeichnishierarchien nebeneinander an, wobei alle gemeinsamen Abschnitte gefaltet sind.

garyjohn
quelle
+1 für nette UI-Lösung, ohne zusätzliche Dateien zu erstellen
Griddo
Diese Lösung schlägt nach dem Zufallsprinzip fehl. Wenn vim den temporären Dateideskriptor liest (oder erneut liest), ist er bereits verschwunden.
Denilson Sá Maia
23

Ich benutze normalerweise rsync für diese Aufgabe:

rsync -nav --delete DIR1/ DIR2

SEI SEHR VORSICHTIG immer das benutzen -naka --dry-run, Option, oder es werden die Verzeichnisse synchronisiert (der Inhalt wird geändert).

Dadurch werden Dateien anhand der Änderungszeiten und -größen verglichen ... I denken das willst du wirklich oder zumindest stört es dich nicht, wenn es das tut? Ich habe das Gefühl, dass Sie nur wollen, dass es passiert schneller Nicht, dass Sie es brauchen, um den Unterschied zwischen Dateiinhalten zu ignorieren. Wenn Sie nicht möchten, dass es unterschiedliche Dateien mit identischen Namen auflistet, denke ich, dass der Zusatz --ignore-existing Option wird das tun.

Seien Sie sich auch bewusst, dass Sie keine setzen / am Ende von DIR1 wird es veranlassen, die zu vergleichen Verzeichnis DIR1 mit dem Inhalt von DIR2.

Die Ausgabe ist etwas ausführlich, zeigt Ihnen jedoch, welche Dateien / Verzeichnisse unterschiedlich sind. Dateien / Verzeichnisse in DIR2 und nicht in DIR1 wird mit dem Wort eingeleitet deleting.

In einigen Situationen ist die Antwort von @ slartibartfast möglicherweise geeigneter, obwohl Sie die entfernen müssen -type d Option zum Aktivieren der Auflistung von Nicht-Verzeichnisdateien. rsync wird schneller sein, wenn Sie eine erhebliche Anzahl von Dateien / Verzeichnissen zum Vergleichen haben.

intuited
quelle
Hervorragende Antwort. In der Ausgabe von rsync ist das kaum zu bemerken deleting... Text, aber es ist wahrscheinlich eine der besseren Möglichkeiten, Dateien zu vergleichen, während die Geschwindigkeit erhalten bleibt. Andere Antworten hier sind schneller, wenn das Vergleichen von Dateien nicht erforderlich ist ... wie im Beispiel von OP, aber ich mag dieses wirklich.
Joel Mellon
Das war es, was ich wollte. Ich hatte einige Dateien mit unterschiedlichen Größen in einem massiven Paar von Verzeichnisbäumen und wollte wissen, welche. Dieses Ziel wurde in wenigen Sekunden erreicht.
suprjami
Vielleicht ist es eine gute Idee, es mit einem Benutzer auszuführen, der nur Lesezugriff hat. Mögen sudo -u nobody rsync -nav --delete d1 d2 vorausgesetzt, die Flags für 'Andere' erlauben das Lesen.
user1182474
Beim Ausführen dieser Lösung wurde "Dateiliste erstellen ... fertig \ n X Bytes gesendet, Y Bytes empfangen, Z Bytes / Sek. Gesamtgröße ist A Geschwindigkeit ist B" (wobei ich XYZAB für Zahlen eingesetzt habe). Bedeutet das, dass alles identisch war? Da es nichts Konkretes erwähnt? Danke im Voraus
Scott H
Um meine eigene Frage zu beantworten, habe ich experimentiert, indem ich zu jeder Datei unterschiedliche Dateien hinzugefügt habe. Es scheint, dass keine bestimmten Dateien / Verzeichnisse, die in der Ausgabe erwähnt werden, bedeuten, dass sie alle gleich sind.
Scott H
16

Ähnlich der Antwort von ls, aber wenn Sie installieren Baum dann kannst du

tree dir1 > out1
tree dir2 > out2
diff out1 out2
digit
quelle
6
Oder die tmpfiles zu vermeiden, diff <( tree dir1 ) <( tree dir2 )
Joel Mellon
1
Ich empfehle den Baum mit der i Flagge, die die Baumlinien nicht druckt ( tree -i dir1, usw). Wenn sich die Verzeichnisstruktur an einer Stelle unterscheidet, weisen die anderen Dateien, die übereinstimmen, möglicherweise mehr oder weniger auf | Symbole in der Baumausgabe und diff werden diese Zeilen auch dann abfangen, wenn die Dateipfade identisch sind.
askewchan
2
diff & lt; (tree -i dir1) & lt; (tree -i dir2) ist bei weitem die beste Antwort. Ich bin versucht, alle Antworten, die diff oder rsync vorschlagen, abzulehnen, da die Frage ausdrücklich besagt, dass der Dateiinhalt NICHT gelesen werden soll. HINWEIS: Der Vorschlag, zwei Rohre zu verwenden, erfordert die sorgfältige Verwendung von Abständen zwischen den Klammern. Befolgen Sie das Beispiel genau. Z.B. Um zwei 20G-Volumes nach einer Sicherung zu vergleichen, dauerte die Baumantwort ungefähr 5 Sekunden. Die anderen dauerten mehr als 20 Minuten.
Jason Morgan
3

Ich habe nur nach einer Lösung für dieses Problem gesucht. Die Lösung, die mir am besten gefallen hat, war:

comm <(ls DIR1) <(ls DIR2)

Sie erhalten 3 Spalten: 1 - Dateien nur in DIR1, 2 - Dateien nur in DIR2, 3 - Dateien nur in DIR3 Weitere Details finden Sie hier Blogeintrag.

kyrisu
quelle
Wo ist DIR3 spezifizierten? Ich sehe nur DIR1 und DIR2.
Michael Dorst
Ich habe es versucht, und (soweit ich das beurteilen kann) war die Ausgabe: Alle Dateien nur in DIR1 im Spalte 1 , alle Dateien nur in DIR2 im Spalte 2 und alle Dateien von beiden geteilt im Spalte 3 . Das ist irgendwie nützlich, aber weißt du, wie man sich ausziehen könnte? Spalte 3 und nur die Unterschiede lassen? Ich habe ein Menge von Dateien zu sortieren, und die meisten davon sind identisch. Ich muss nicht sehen, was das Gleiche ist.
Michael Dorst
1
Das habe ich auch gefunden comm <(ls DIR1) <(ls DIR2) hat nicht rekursiv funktioniert. Dafür habe ich verwendet comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -R durchsucht rekursiv durch Verzeichnisse und ls -1 (Beachten Sie, dass dies ein ist ein nicht ein L ) macht ls Gib nur einen Dateinamen pro Zeile aus.
Michael Dorst
@Michael: comm -3 (sehen man comm ).
Zaz
2
ls > dir1.txt

ls > dir2.txt

Dann vergleichen Sie einfach die beiden Listen.

MDMarra
quelle
Es scheint, als wolle das OP eine Hierarchie von Pfaden. Dies unterscheidet alle Dateien im aktuellen Verzeichnis. Es ist fraglich, aber möglich, dass er nur Verzeichnisse will; er möchte vielleicht eher Dateinamen als den Inhalt von Dateien.
intuited
@intuited - du hast recht. Ich habe es falsch verstanden.
MDMarra
2

Dies ist die optimale Lösung

diff --brief -r dir1 dir2

- Briefwechsel meldet nur, ob sich die Dateien unterscheiden, nicht die Details der Differenz.

jkshah
quelle
1
Das OP hat schon -q in der frage ist das ein alias für --brief. Diese Antwort liefert keine neuen Informationen.
Michael Dorst
1
OP möchte nicht, dass der Dateiinhalt verglichen wird. But it's really slow because it's comparing files too.
Joel Mellon
1

Verwenden Sie "diff -qr", um die verschiedenen Dateien abzurufen, und filtern Sie dann den Dateivergleich mit grep heraus, um nur die Dateinamen zu erhalten, die sich nur in einem der Verzeichnisse befinden.

diff -qr dir1 dir2 | grep -v "Files.*differ" 
Anonymous
quelle
-3

Ich denke, nur Rsync ist nützlich. Warum?

diff ist nur für Strukturen nützlich, die Dateien und Verzeichnisse enthalten. Diff verwendet keine ausreichenden Beendigungscodes, wenn wir Symlinks verwenden. In dieser Situation kann diff 2 Exitcodes zurückgeben, auch wenn src und dst identisch sind (Zeiten, Größen, Namen, Zeitstempel, Softlinks zum Zeigen usw.).

Das Dateisystem garantiert nicht die Reihenfolge der Dateien, selbst wenn der Inhalt von src und dst identisch ist. Vielleicht sollten Sie die Ausgabe von ls filtern, indem Sie sie sortieren. Pure ls zeigt jedoch nur Knotennamen an.

Vielleicht ist ein Skript mit diff, cmp und test -X für Knotentypen nützlich, aber denken Sie daran, dass viele Test- / cmp-Läufe eine Überlastung verursachen. Das Skript wird sehr langsam sein.

Wenn Sie wie üblich die einfache Information "dirs ist / ist nicht identisch" erhalten möchten, sollten Sie rsync mit der Option -n (dry) verwenden. Wenn Sie herausfinden möchten, was anders ist, verwenden Sie den Befehl diff.

Znik
quelle
Ich würde gerne wissen, warum Minuspunkte?
Znik