it-swarm.com.de

Unterschied zwischen zwei Verzeichnissen in Linux

Ich versuche, die Dateien in einem Verzeichnis zu finden, aber nicht im anderen. Ich habe versucht, diesen Befehl zu verwenden:

diff -q dir1 dir2

Das Problem mit dem obigen Befehl, dass er sowohl die Dateien in dir1 aber nicht in dir2 findet, als auch die Dateien in dir2 aber nicht in dir1

Ich versuche, die Dateien in dir1 zu finden, aber nicht nur in dir2.

Hier ist ein kleiner Ausschnitt dessen, wie meine Daten aussehen

dir1    dir2    dir3
1.txt   1.txt   1.txt
2.txt   3.txt   3.txt
5.txt   4.txt   5.txt
6.txt   7.txt   8.txt

Eine andere Frage ist, wie ich die Dateien in dir1 finden kann, aber nicht in dir2 oder dir3 in einem einzigen Befehl.

242
Error404
diff -r dir1 dir2 | grep dir1 | awk '{print $4}' > difference1.txt

Erklärung:

  • diff -r dir1 dir2 zeigt an, welche Dateien nur in dir1 und diejenigen nur in dir2 sind, und auch die Änderungen der Dateien, die in beiden Verzeichnissen vorhanden sind.

  • diff -r dir1 dir2 | grep dir1 zeigt, welche Dateien sich nur in dir1 befinden

  • awk, um nur den Dateinamen zu drucken.

343
asclepix

Dies sollte die Arbeit erledigen:

diff -rq dir1 dir2

Optionen erklärt (via diff (1) manpage ):

  • -r - Rekursiv alle gefundenen Unterverzeichnisse vergleichen.
  • -q - Nur ausgeben, wenn sich Dateien unterscheiden.
102
tokhi
comm -23 <(ls dir1 |sort) <(ls dir2|sort)

Mit diesem Befehl erhalten Sie Dateien, die sich in dir1 und nicht in dir2 befinden.

Über <( ) sign können Sie es als "Prozessersetzung" googeln.

45
plhn

Eine gute Möglichkeit für diesen Vergleich ist die Verwendung von find mit md5sum und dann einer diff.

Beispiel:

Verwenden Sie find, um alle Dateien im Verzeichnis aufzulisten, berechnen Sie dann den md5-Hash für jede Datei und leiten Sie ihn an eine Datei weiter:

find /dir1/ -type f -exec md5sum {} \; > dir1.txt

Führen Sie dasselbe Verfahren für ein anderes Verzeichnis aus:

find /dir2/ -type f -exec md5sum {} \; > dir2.txt

Vergleichen Sie dann das Ergebnis zwei Dateien mit "diff":

diff dir1.txt dir2.txt

Diese Strategie ist sehr nützlich, wenn sich die beiden zu vergleichenden Verzeichnisse nicht auf derselben Maschine befinden und Sie sicherstellen müssen, dass die Dateien in beiden Verzeichnissen gleich sind.

Eine andere gute Möglichkeit, den Job zu erledigen, ist die Verwendung von git

git diff --no-index dir1/ dir2/

Freundliche Grüße!

27
Adail Junior

Meld ( http://meldmerge.org/ ) ist ein hervorragender Job beim Vergleichen von Verzeichnissen und den darin enthaltenen Dateien.

 Meld comparing directories

13
Catalin Hritcu

das DirDiff Plugin von vim ist ein weiteres sehr nützliches Werkzeug zum Vergleichen von Verzeichnissen.

vim -c "DirDiff dir1 dir2"

Es listet nicht nur auf, welche Dateien zwischen den Verzeichnissen unterschiedlich sind, sondern ermöglicht Ihnen auch, mit vimdiff zu prüfen, welche Dateien unterschiedlich sind.

10
drrossum

Unzufrieden mit allen Antworten, da die meisten von ihnen sehr langsam arbeiten und unnötig lange Ausgaben für große Verzeichnisse erzeugen, schrieb ich mein eigenes Python-Skript, um zwei Ordner zu vergleichen.

Im Gegensatz zu vielen anderen Lösungen wird der Inhalt der Dateien nicht verglichen. Es geht auch nicht in Unterverzeichnisse, die in einem anderen Verzeichnis fehlen. Die Ausgabe ist also recht knapp und das Skript funktioniert schnell.

#!/usr/bin/env python3

import os, sys

def compare_dirs(d1: "old directory name", d2: "new directory name"):
    def print_local(a, msg):
        print('DIR ' if a[2] else 'FILE', a[1], msg)
    # ensure validity
    for d in [d1,d2]:
        if not os.path.isdir(d):
            raise ValueError("not a directory: " + d)
    # get relative path
    l1 = [(x,os.path.join(d1,x)) for x in os.listdir(d1)]
    l2 = [(x,os.path.join(d2,x)) for x in os.listdir(d2)]
    # determine type: directory or file?
    l1 = sorted([(x,y,os.path.isdir(y)) for x,y in l1])
    l2 = sorted([(x,y,os.path.isdir(y)) for x,y in l2])
    i1 = i2 = 0
    common_dirs = []
    while i1<len(l1) and i2<len(l2):
        if l1[i1][0] == l2[i2][0]:      # same name
            if l1[i1][2] == l2[i2][2]:  # same type
                if l1[i1][2]:           # remember this folder for recursion
                    common_dirs.append((l1[i1][1], l2[i2][1]))
            else:
                print_local(l1[i1],'type changed')
            i1 += 1
            i2 += 1
        Elif l1[i1][0]<l2[i2][0]:
            print_local(l1[i1],'removed')
            i1 += 1
        Elif l1[i1][0]>l2[i2][0]:
            print_local(l2[i2],'added')
            i2 += 1
    while i1<len(l1):
        print_local(l1[i1],'removed')
        i1 += 1
    while i2<len(l2):
        print_local(l2[i2],'added')
        i2 += 1
    # compare subfolders recursively
    for sd1,sd2 in common_dirs:
        compare_dirs(sd1, sd2)

if __name__=="__main__":
    compare_dirs(sys.argv[1], sys.argv[2])

Verwendungsbeispiel:

[email protected]:~$ python3 compare_dirs.py dir1/ dir2/
DIR  dir1/out/flavor-domino removed
DIR  dir2/out/flavor-maxim2 added
DIR  dir1/target/vendor/flavor-domino removed
DIR  dir2/target/vendor/flavor-maxim2 added
FILE dir1/tmp/.kconfig-flavor_domino removed
FILE dir2/tmp/.kconfig-flavor_maxim2 added
DIR  dir2/tools/tools/LiveSuit_For_Linux64 added

Oder wenn Sie nur Dateien aus dem ersten Verzeichnis anzeigen möchten: 

[email protected]:~$ python3 compare_dirs.py dir2/ dir1/ | grep dir1
DIR  dir1/out/flavor-domino added
DIR  dir1/target/vendor/flavor-domino added
FILE dir1/tmp/.kconfig-flavor_domino added

P.S. Wenn Sie die Dateigrößen und Datei-Hashwerte für mögliche Änderungen vergleichen müssen, habe ich hier ein aktualisiertes Skript veröffentlicht: https://Gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779

9
Andriy Makukha

Ein weiterer Ansatz (möglicherweise schneller für große Verzeichnisse):

$ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt
$ diff dir1.txt dir2.txt

Der Befehl sed entfernt die erste Verzeichniskomponente dank Eriks Beitrag )

5
jaltek

Dies ist etwas spät, kann aber jemandem helfen. Nicht sicher, ob diff oder rsync nur Dateinamen in einem bloßen Format wie diesem ausspuckt. Danke an plhn für die schöne Lösung, auf die ich unten eingegangen bin.

Wenn Sie nur die Dateinamen benötigen, um die gewünschten Dateien einfach in einem sauberen Format zu kopieren, können Sie den Befehl find verwenden.

comm -23 <(find dir1 | sed 's/dir1/\//'| sort) <(find dir2 | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

Dies setzt voraus, dass sich dir1 und dir2 im selben übergeordneten Ordner befinden. sed entfernt nur den übergeordneten Ordner, damit Sie Äpfel mit Äpfeln vergleichen können. Der letzte sed setzt nur den dir1-Namen zurück.

Wenn Sie nur Dateien wünschen:

comm -23 <(find dir1 -type f | sed 's/dir1/\//'| sort) <(find dir2 -type f | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

Ähnlich für Verzeichnisse:

comm -23 <(find dir1 -type d | sed 's/dir1/\//'| sort) <(find dir2 -type d | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'
4
James

Die akzeptierte Antwort listet auch die Dateien auf, die in beiden Verzeichnissen vorhanden sind, aber unterschiedlichen Inhalt haben. Um NUR die in dir1 vorhandenen Dateien aufzulisten, können Sie Folgendes verwenden:

diff -r dir1 dir2 | grep 'Only in' | grep dir1 | awk '{print $4}' > difference1.txt

Erläuterung: 

  • diff -r dir1 dir2: vergleichen
  • grep 'Only in': Liefert Zeilen mit 'Only in'
  • grep dir1: Liefert Zeilen, die dir enthalten
4
Aris

Dies ist das Bash-Skript zum Drucken von Befehlen zum Synchronisieren zweier Verzeichnisse

dir1=/tmp/path_to_dir1
dir2=/tmp/path_to_dir2
diff -rq $dir1 $dir2 | sed -e "s|Only in $dir2\(.*\): \(.*\)|cp -r $dir2\1/\2 $dir1\1|" |  sed -e "s|Only in $dir1\(.*\): \(.*\)|cp -r $dir1\1/\2 $dir2\1|" 
1
Ebru Yener

Diese Antwort optimiert einen der Vorschläge von @ Adail-Junior durch Hinzufügen der Option -D, was hilfreich ist, wenn keines der zu vergleichenden Verzeichnisse git-Repositorys sind:

git diff -D --no-index dir1/ dir2/

Wenn Sie -D verwenden, werden keine Vergleiche mit /dev/null: text Binary files a/whatever and /dev/null differ angezeigt.

1
Mike Slinn

GNU grep kann die Suche mit der Option -v umkehren. Dies führt dazu, dass grep die Zeilen meldet, die nicht übereinstimmen. Auf diese Weise können Sie die Dateien in dir2 aus der Liste der Dateien in dir1 entfernen.

grep -v -F -x -f <(find dir2 -type f -printf '%P\n') <(find dir1 -type f -printf '%P\n')

Die Optionen -F -x weisen grep an, eine Zeichenfolgesuche in der gesamten Zeile durchzuführen.

0
ceving

Eine vereinfachte Methode zum Vergleichen von 2 Verzeichnissen mithilfe des Befehls DIFF

diff Dateiname.1 Dateiname.2> Dateiname.dat >> Eingeben

Öffnen Sie Dateiname.dat, nachdem der Lauf abgeschlossen ist

und Sie sehen: Nur in Dateiname.1: Dateiname.2 Nur in: Verzeichnisname: Dateiname1 Nur in: Verzeichnisname: Dateiname2

0
nerakk

kdiff3 hat eine Nice Diff-Schnittstelle für Dateien und Verzeichnisse.

Es funktioniert unter Windows, Linux und Mac OS.

Sie können es auf verschiedene Arten installieren:

0
ayakout