diff, um nur die Dateinamen auszugeben


243

Ich möchte einen Linux-Befehl ausführen, der zwei Verzeichnisse rekursiv vergleicht und nur die Dateinamen der Unterschiede ausgibt . Dies schließt alles ein, was in einem Verzeichnis und nicht im anderen oder umgekehrt vorhanden ist, sowie Textunterschiede.

Antworten:


374

Von der Diff-Manpage:

-q   Geben Sie nur an, ob sich die Dateien unterscheiden, nicht die Details der Unterschiede.
-r   Vergleichen Sie beim Vergleichen von Verzeichnissen rekursiv alle gefundenen Unterverzeichnisse.

Beispielbefehl:

diff -qr dir1 dir2

Beispielausgabe (abhängig vom Gebietsschema):

$ ls dir1 dir2
dir1:
same-file  different  only-1

dir2:
same-file  different  only-2
$ diff -qr dir1 dir2
Files dir1/different and dir2/different differ
Only in dir1: only-1
Only in dir2: only-2

Vielen Dank - die diffManpage in CentOS 7 beschreibt -q"Nur melden, wenn sich Dateien unterscheiden", was weniger klar ist als das, was Sie geschrieben haben.
Kap

2
Dies vergleicht den tatsächlichen Inhalt der Dateien, was häufig gewünscht wird. Die rsync-Antwort bietet jedoch die Möglichkeit, nur die Dateinamen und -größen und nicht den Inhalt anzuzeigen. das ist manchmal wünschenswert.
Steveb

Funktioniert auch unter macOS.
Marius Soutier

Kann auch -x PATTERNin den Befehl einschließen , um bestimmte Unterverzeichnisse auszuschließen. Zum Beispiel diff -qr repo1 repo2 -x ".git" werden zwei Verzeichnisse vergleichen , sondern wird Dateipfade mit „.git“ in ihnen auszuschließen.
ViFI

27

Sie können auch rsync verwenden

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out

6
--size-onlyEs fehlen Dateien mit identischer Größe, aber unterschiedlichem Inhalt, z. B. old / version.txt "29a" new / version.txt "29b" . Verwenden Sie stattdessen: rsync -ric --dry-run old/ new/wobei das Argument "-i" es ermöglicht, die Dateiliste direkt überrsync -ric --dry-run old/ new/ | cut -d" " -f 2
iolsmit am

6
Dies ist ideal, wenn Sie nur nach fehlenden Dateien suchen (insbesondere über Netzwerkfreigaben hinweg), da der Inhalt nicht verglichen wird. Dies hat mir geholfen, einige Dateien zu finden, die bei der Migration auf ein neues NAS fehlgeschlagen sind.
OverZealous

4
Stellen Sie sicher, dass Sie den abschließenden Schrägstrich für Pfade einfügen, die in der Befehlszeile von rsync angegeben sind. Ohne sie funktioniert dies nicht richtig und rsync zählt wahrscheinlich nur alle Dateinamen auf!
Vladimir Panteleev

2
In Bezug auf die Kommentare zur Nichtprüfung des Inhalts. Dies ist manchmal wünschenswert, zumindest als erster Durchgang.
Steveb

13

Wenn Sie eine Liste von Dateien erhalten möchten, die sich nur in einem Verzeichnis befinden und nicht deren Unterverzeichnisse und nur deren Dateinamen:

diff -q /dir1 /dir2 | grep /dir1 | grep -E "^Only in*" | sed -n 's/[^:]*: //p'

Wenn Sie rekursiv alle Dateien und Verzeichnisse auflisten möchten, die sich mit ihren vollständigen Pfaden unterscheiden:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}'

Auf diese Weise können Sie auf alle Dateien unterschiedliche Befehle anwenden.

Zum Beispiel könnte ich alle Dateien und Verzeichnisse entfernen, die sich in dir1, aber nicht in dir2 befinden:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}' xargs -I {} rm -r {}

9

Auf meinem Linux-System bekomme ich nur die Dateinamen

diff -q /dir1 /dir2|cut -f2 -d' '

7
Ich füge meinem Linux-System keine Dateinamen mit Leerzeichen hinzu. ;)
gerardw

6
Ich wollte dir das nicht zuschreiben ... ;-p Nur als Hinweis für jemanden, der es tut ...
michuelnik

funktioniert bei mir nicht Meine Verzeichnisstruktur ist wie folgtaudit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy

diff -qrN /dir1 /dir2 | cut -f2 -d' 'funktioniert gut für mich!
Francesco

9

Der Ausführungsansatz diff -qr old/ new/hat einen großen Nachteil: Möglicherweise fehlen Dateien in neu erstellten Verzeichnissen. Im folgenden Beispiel befindet sich die Datei data/pages/playground/playground.txtbeispielsweise nicht in der Ausgabe von, diff -qr old/ new/während sich das Verzeichnis data/pages/playground/befindet (suchen Sie in Ihrem Browser nach playground.txt, um sie schnell zu vergleichen). Ich habe auch die folgende Lösung auf Unix & Linux Stack Exchange veröffentlicht , aber ich werde sie auch hier kopieren:

Um eine Liste neuer oder geänderter Dateien programmgesteuert zu erstellen, ist die beste Lösung, die ich finden könnte, die Verwendung von rsync , sort und uniq :

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

Lassen Sie mich anhand dieses Beispiels erklären: Wir möchten zwei Dokuwiki-Versionen vergleichen, um festzustellen, welche Dateien geändert und welche neu erstellt wurden.

Wir holen die Teere mit wget und extrahieren sie in die Verzeichnisse old/und new/:

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

Wenn Sie rsync auf eine Weise ausführen, werden möglicherweise neu erstellte Dateien übersehen, wie der Vergleich von rsync und diff hier zeigt:

rsync -rcn --out-format="%n" old/ new/

ergibt folgende Ausgabe:

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

Wenn Sie rsync nur in eine Richtung ausführen, werden die neu erstellten Dateien übersehen, und umgekehrt würden gelöschte Dateien übersehen. Vergleichen Sie die Ausgabe von diff:

diff -qr old/ new/

ergibt folgende Ausgabe:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

Wenn Sie rsync in beide Richtungen ausführen und die Ausgabe sortieren, um Duplikate zu entfernen, werden das Verzeichnis data/pages/playground/und die Datei data/pages/playground/playground.txtanfangs übersehen:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

ergibt folgende Ausgabe:

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync wird mit diesen Argumenten ausgeführt:

  • -r "in Verzeichnisse zurückgreifen",
  • -c um auch Dateien mit identischer Größe zu vergleichen und nur "basierend auf Prüfsumme zu überspringen, nicht Mod-Zeit & Größe",
  • -n um "einen Probelauf ohne vorgenommene Änderungen durchzuführen" und
  • --out-format="%n" um "Aktualisierungen mit dem angegebenen FORMAT auszugeben", das hier nur für den Dateinamen "% n" ist

Die Ausgabe (Liste der Dateien) rsyncin beide Richtungen wird kombiniert und sortiert mit sort, und diese sortierte Liste wird dann komprimiert, indem alle Duplikate mit entfernt werdenuniq


Könnten Sie es nicht einfach rückwärts ausführen ( diff new/ old/), um zu sehen, welche Verzeichnisse gelöscht wurden?
Jacques

Das Ausführen diff -qr new/ old/des obigen Beispiels mit den Dokuwiki-Teeren erzeugt die gleiche Ausgabe wie diff -qr old/ new/- dh Sie sehen, dass das Verzeichnis neu ist / fehlt, aber nicht die darin enthaltenen Dateien
iolsmit

-4
rsync -rvc --delete --size-only --dry-run source dir target dir
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.