Wie kann ich anhand von zwei Verzeichnisbäumen herausfinden, welche Dateien sich nach Inhalt unterscheiden?

786

Wenn ich die Unterschiede zwischen zwei Verzeichnisbäumen finden möchte, führe ich normalerweise einfach Folgendes aus:

diff -r dir1/ dir2/

Dies gibt genau die Unterschiede zwischen den entsprechenden Dateien aus. Ich bin daran interessiert, nur eine Liste der entsprechenden Dateien zu erhalten, deren Inhalt unterschiedlich ist. Ich nahm an, dass dies einfach eine Frage der Übergabe einer Befehlszeilenoption sein würde diff, aber ich konnte auf der Manpage nichts finden.

Irgendwelche Vorschläge?

Mansoor Siddiqui
quelle
1
Wie kann man in Bezug auf eines der Verzeichnisse nur die Dateien / Verzeichnisse erhalten, die in dem anderen zusätzlich enthalten sind?
Sandeepan Nath
Verwenden Sie den dircmpBefehl unter Unix (nicht Linux)
Roblogic

Antworten:

1119

Sie sagten Linux, also haben Sie Glück (zumindest sollte es verfügbar sein, nicht sicher, wann es hinzugefügt wurde):

diff --brief --recursive dir1/ dir2/ # GNU long options
diff -qr dir1/ dir2/ # common short options

Sollte tun, was Sie brauchen.

Wenn Sie auch Unterschiede für Dateien sehen möchten, die möglicherweise in keinem der beiden Verzeichnisse vorhanden sind:

diff --brief --recursive --new-file dir1/ dir2/ # GNU long options
diff -qrN dir1/ dir2/ # common short options
Mark Loeser
quelle
12
Nett. Aber kürzer ist diff -qr dir1/ dir2/und meine erweiterte Version zudiff -qr dir1/ dir2/ | grep ' differ'
sobi3ch
1
@skv warum? Es ist der gleiche Befehl wie die Antwort. Ich habe nur --briefdie Verknüpfung geändert -q.
sobi3ch
2
@skv Nicht genau das, was die ursprüngliche Frage gestellt hat, aber die Antwort wird aktualisiert, um auch dieser Frage Rechnung zu tragen.
Mark Loeser
3
@ MikeMaxwell Es muss sein --brief. -briefwird interpretiert als -b -r -i -e -f, mit anderen Worten als eine Reihe von Flags, nicht als eine einzelne Option.
Daboross
2
@daboross: Wow, ich benutze Unix / Linux schon seit einiger Zeit und habe nie bemerkt, dass es diesen Unterschied zwischen '-' und '-' gibt. (Ich glaube nicht, dass '-' existiert hat, als ich angefangen habe.) Danke für die Erklärung!
Mike Maxwell
287

Der Befehl, den ich benutze, ist:

diff -qr dir1/ dir2/

Es ist genau das gleiche wie bei Marks :) Aber seine Antwort hat mich gestört, da es verschiedene Arten von Flaggen verwendet und ich zweimal hinschauen musste. Mit Marks ausführlicheren Flags wäre es:

diff  --brief --recursive dir1/ dir2/

Ich entschuldige mich für die Veröffentlichung, wenn die andere Antwort vollkommen akzeptabel ist. Konnte mich nicht aufhalten ... daran zu arbeiten, weniger pedantisch zu sein.

FPC
quelle
3
Schätzen Sie die Beständigkeit voll und ganz - aber fühlen Sie sich nicht schlecht. Ich habe auch Marks Antwort positiv bewertet;)
Gerard ONeill
10
..so macht es Sinn, unterschiedliche Antworten mit NUR einem anderen Geschmack zu geben? IMHO nein! Ist es sinnvoll, beide Antworten zu einer einheitlichen Antwort zu kombinieren? Ja! ;)
sobi3ch
1
Nur eine Frage; Wofür steht das q? Ist es eine Abkürzung für etwas? Ich kann keine Logik hinter dem finden q.
kramer65
3
@ kramer65 - es ist das gleiche wie "--brief", aber ich denke du fragst dich warum q? Vielleicht für schnell? "-b" wird von "Änderungen in der Größe des Leerraums ignorieren" gemäß der Manpage übernommen.
FPC
4
@ kramer65 Ich glaube das qist für quiet, was im Allgemeinen weniger ausführlich bedeutet.
Gogeta70
105

Ich verwende es gerne git diff --no-index dir1/ dir2/, weil es die Farbunterschiede anzeigen kann (wenn Sie diese Option in Ihrer Git-Konfiguration festgelegt haben) und weil es alle Unterschiede in einer Ausgabe mit langen Seiten mit "weniger" anzeigt.

Alan Porter
quelle
25
Ordentlich. Wer hätte gedacht, dass Git beliebige Verzeichnisse unterscheiden kann, nicht nur das Repo gegen seine Dateien?
Dan Dascalescu
2
Perl Script Colordiff ist hier sehr nützlich, kann mit svn und normal diff verwendet werden.
Felipe Alvarez
4
Wenn Sie (wie ich) 2 Verzeichnisse als separate Git-Projekte / Repos vergleichen, müssen Sie --no-indexunter stackoverflow.com/a/1792477/473390 weitere hinzufügen . Ich habe die Antwort von @ alan-porter aktualisiert.
sobi3ch
Ich mag dieses, ich finde auch, dass, wenn Sie --name-status zur Befehlszeile hinzufügen , es nur die Dateinamenliste mit "M / A / D" -Flaggen für den Status Geändert / Hinzugefügt / Gelöscht anzeigt.
27.
Es kommt vor, dass beide Verzeichnisse tatsächlich den Ordner .git enthalten. Wie kann ich ihn vom Vergleich ausschließen?
Muhamed Cicak
35

Diese beiden Befehle erfüllen im Grunde die Anforderungen:

diff --brief --recursive --no-dereference --new-file --no-ignore-file-name-case /dir1 /dir2 > dirdiff_1.txt

rsync --recursive --delete --links --checksum --verbose --dry-run /dir1/ /dir2/ > dirdiff_2.txt

Die Wahl zwischen ihnen hängt von der Position von dir1 und dir2 ab:

Wenn sich die Verzeichnisse auf zwei separaten Laufwerken befinden, übertrifft diff rsync. Wenn sich die beiden verglichenen Verzeichnisse jedoch auf demselben Laufwerk befinden, ist rsync schneller. Dies liegt daran, dass diff beide Verzeichnisse parallel fast gleich stark belastet und so die Belastung der beiden Laufwerke maximiert.

rsync berechnet Prüfsummen in großen Blöcken, bevor sie tatsächlich verglichen werden. Dies gruppiert die E / A-Vorgänge in großen Blöcken und führt zu einer effizienteren Verarbeitung, wenn Dinge auf einem einzelnen Laufwerk stattfinden.

CodeBug
quelle
3
rsync ist nicht nur schneller für Dateien auf einzelne Laufwerke, sondern auch allowes für Dateien in subdirs, zum Beispiel zu vergleichen rsync --options /usr /bin /var /sbin /lib /old_rooteffektiv aktuellen Root vergleichen /(durch alle subdirs darin Angabe) und /old_root(enthält zum Beispiel eine ältere Sicherung /), die etwas ist , diff -rkann nicht tun. Und wenn Sie feststellen , dass Dateien mit gleicher Größe, Berechtigungen übernehmen und Zeitstempel haben wahrscheinlich nicht geändert, Weglassen --checksumwerden Sie mit extrem schnell (wenn auch nicht so durch) Kontrolle , welche Dateien geändert haben könnten.
Matija Nalis
1
Was ist der Zweck von --deletemit rsync?
Tom Hale
2
Der Zweck von --delete ist es, vorhandene Dateien im Zielverzeichnis zu löschen, die (nicht mehr) im Quellverzeichnis vorhanden sind
Thomas Munk
2
In diesem Fall (mit dem --dry-runFlag) wird nichts wirklich gelöscht, rsyncsondern nur gedruckt, welche Dateien sich in dir1, aber nicht in dir2 befinden
mata
11
Ich würde empfehlen, --dry-runimmer an erster Stelle zu stehen, um es nicht versehentlich zu vergessen.
Dave Rager
22

Meld ist auch ein großartiges Tool zum Vergleichen von zwei Verzeichnissen:

meld dir1/ dir2/

Meld bietet viele Optionen zum Vergleichen von Dateien oder Verzeichnissen. Wenn sich zwei Dateien unterscheiden, können Sie leicht in den Dateivergleichsmodus wechseln und die genauen Unterschiede erkennen.

Alexander
quelle
2
Nett. Ich habe ein einfaches Perl-Skript geschrieben, um einen Vergleich über Bäume durchzuführen, aber ich stoße auf Einschränkungen. Dies scheint das Ticket zu sein.
David Tonhofer
Das einzige Problem ist, dass es sich nicht für Skripte eignet, da es sich um eine grafische App handelt. Aber es ist schön, wenn Ihnen die GUI nichts ausmacht! Vielen Dank.
DeanM
Ich finde, dass melddas schrecklich träge wird, wenn es in großen Verzeichnissen verwendet wird. Gibt es etwas, das große Verzeichnisse besser handhabt?
Popup
@ Popup, nicht das ich wüsste. Sie könnten jedoch unterschiedliche Dateinamen mit so etwas finden:find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique
Alexander
1
@Alexander - In diesem Fall meld <(find dir1 -ls ) <(find dir2 -ls)funktioniert das ziemlich gut, wenn man die Bash-Prozess-Substitution verwendet. (zsh =(command)funktioniert noch besser.)
Popup
10

Channel-Landsmann 'Billings' (von Freenode / # Centos Ruhm) teilte mir seine Methode mit:

diff -Naur dir1/ dir2

Das Einfügen des endgültigen Verzeichnis-Schrägstrichs spielt keine Rolle.

Außerdem scheint die -uOption bei einigen älteren / Server-Versionen von diff nicht verfügbar zu sein.

Der Unterschied in den Unterschieden:

# diff -Nar /tmp/dir1 /tmp/dir2/
diff -Nar /tmp/dir1/file /tmp/dir2/file
28a29
> TEST

# diff -qr /tmp/dir1/ /tmp/dir2/
Files /tmp/dir1/file and /tmp/dir2/file differ
todd_dsm
quelle
2
Das ist es, --new-file/-Nwas diff dazu veranlasst, fehlende Dateien als leer --text/-azu betrachten und alle Binäreingaben als Text zu betrachten. Ich sehe die Vorteile für diesen speziellen Anwendungsfall nicht.
Phk
4

Diffoscope ist ein großartiges befehlszeilenbasiertes Verzeichnisdiff-Tool.

Mir gefällt besonders, dass es sich in Dateien unterscheiden kann:

Es entpackt rekursiv Archive verschiedener Art und wandelt verschiedene Binärformate in eine besser lesbare Form um, um sie zu vergleichen. Genauso einfach können zwei Tarballs, ISO-Images oder PDFs verglichen werden.

Hier erfahren Sie nicht nur, welche Dateien sich unterscheiden, sondern auch, wie sie sich unterscheiden.

nh2
quelle
4

Verwenden Sie diesen Befehl, um diff zu finden:

diff -qr dir1/ dir2/

-r unterscheidet auch alle Unterverzeichnisse. -q weist diff an, nur dann zu melden, wenn sich die Dateien unterscheiden.

diff  --brief dir1/ dir2/

--brief zeigt die Dateien an, die im Verzeichnis vorhanden sind.

Oder aber

Wir können Meld verwenden, das im grafischen Fenster anzeigt, wie leicht der Unterschied zu finden ist.

meld  dir1/ dir2/
Javeed Shakeel
quelle
2
--briefund -qsind die gleiche Option. Ihre Aussage lässt es so klingen, als wären sie unterschiedlich, aber sie sind es nicht.
Elijah Lynn
2

Sie können auch verwendet werden Rsyncund find. Für find:

find $FOLDER -type f | cut -d/ -f2- | sort > /tmp/file_list_$FOLDER

Dateien mit demselben Namen und in denselben Unterordnern, jedoch mit unterschiedlichem Inhalt, werden jedoch nicht in den Listen angezeigt.

Wenn Sie ein Fan von GUI sind, können Sie die Meldung überprüfen , die @Alexander erwähnt hat. Es funktioniert gut in Windows und Linux.

Fábio
quelle
1

Um Unterschiede zwischen dirA und dirB zu melden und gleichzeitig zu aktualisieren / zu synchronisieren.

rsync -auv <dirA> <dirB>

Kickaha
quelle