Mehrere Verzeichnisse vergleichen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 12:24:47

Wir kennen alle sicherlich das Programm diff um 2 Ordner miteinander zu vergleichen.

Code: Alles auswählen

diff -r verzeichnis_1 verzeichnis_2
Aber was ist der effizienteste Weg, wenn man eine ganze Liste an Verzeichnissen 1 bis n hat und diese miteinander unter Berücksichtigung ihrer Unterverzeichnisse vergleichen will.

Man könnte jetzt für jede Kombination einen diff Befehl schreiben. Aber geht das auch irgendwie einfacher, bequemer oder effizienter?

Und gibt es vielleicht eine Möglichkeit Prüfsummen auf ganze Verzeichnisse anzuwenden, also eine einzige Prüfsumme für das gesamte Verzeichnis, dessen Unterverzeichnisse und allen darin enthaltenen Dateien zu erstellen?
Ich meine jetzt also nicht, alle Unterverzeichnisse einzeln durchzugehen und von jeder gefundenen Datei eine Prüfsumme zu erstellen, sondern eben alle Dateien, Unterverzeichnisse usw. in die Berechnung eines einzigen Hash zu führen, so dass man praktisch einen Hash für ein Verzeichnis hat?
Ich frage deswegen, weil man so mehrere Verzeichnisse dann auch ganz einfach vergleichen könnte.

Benutzeravatar
hikaru
Moderator
Beiträge: 13896
Registriert: 09.04.2008 12:48:59

Re: Mehrere Verzeichnisse vergleichen

Beitrag von hikaru » 11.05.2022 12:54:25

Was technisch der effizienteste Weg ist um N Verzeichnisse zu vergleichen weiß ich nicht. Aber wenn du ein Verzaichnis zum "Master-Verzeichnis" erklärst und alle anderen Verzeichnisse nur mit diesem vergleichst, dann kannst du den Vergleichsaufwand drastisch reduzieren, nämlich von (N^2-N)/2 auf N-1.

Was die Prüfsummen angeht, so könntest du zunächst Prüfsummendateien aller Dateien in einem Verzeichnis (mit Unterverzeichnissen) erstellen und dann die Prüfsummendateien vergleichen:

Code: Alles auswählen

find VERZEICHNIS1 -type f -exec md5sum {} + > VERZEICHNIS1.md5
find VERZEICHNIS2 -type f -exec md5sum {} + > VERZEICHNIS2.md5
diff VERZEICHNIS1.md5 VERZEICHNIS2.md5
Wenn du hier einen Unterscheid feststellst, dann kannst du dir diesen im Detail anschauen.

Benutzeravatar
Meillo
Moderator
Beiträge: 9224
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Meillo » 11.05.2022 12:57:29

Die Frage ist doch, *was* du vergleichen willst.

Wenn es dir nur um die Gleichheit geht, dann kannst du auch einfach alle anderen Verzeichnisse mit einem Referenzverzeichnis vergleichen. Das sind n-1 Vergleiche.

Oder du erstellst mit `find|sort' von jedem Verzeichnis eine Dateiliste, speicherst die in eine Datei und vergleichst diese dann (mit `wc' und `diff' oder `comm').

Oder du vergleichst zusaetzlich die Groesse (mit `du').

Aber das haengt in erster Linie davon ab, was genau du wissen willst.

Versuchst du also herauszufinden welche Verzeichnisse exakte Kopien voneinander sind (um die Kopien zu reduzieren)? Oder hast du Quell- und Zielverzeichnisse und willst die abgleichen? Oder hast du verschiedene Versionsstaende und interessierst dich fuer die Aenderungen? All diese Fragen erfordern Vergleiche, aber teilweise in unterschiedlicher Art. Darum ist entscheidend, was du mit den Vergleichen bezwecken willst.
Use ed once in a while!

JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Mehrere Verzeichnisse vergleichen

Beitrag von JTH » 11.05.2022 13:08:38

Meillo hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 12:57:29
Die Frage ist doch, *was* du vergleichen willst.
Unabhängig von dieser mir zum Mittag grad viel zu philosophischen Frage :mrgreen: eine ganz naive Idee: Verzeichnis(se) mit tar packen und Checksumme des Tars berechnen:

Code: Alles auswählen

#!/bin/sh

for dir in "$@"; do
	printf "%s   %s\n" "$(tar -C "$dir" -c --sort=name . | sha512sum | cut -d' ' -f1)" "${dir%/}/"
done

Code: Alles auswählen

$ ./dirsum a/ b/ c/
7c5694f5c9f1ec0048686b302d12a5a2f2850ef01ac04c4a181082da0d5a8035c118a303a9412c6f122544147c1ba3d67ffe6201a8607946c4bab298482dd10f   a/
7c5694f5c9f1ec0048686b302d12a5a2f2850ef01ac04c4a181082da0d5a8035c118a303a9412c6f122544147c1ba3d67ffe6201a8607946c4bab298482dd10f   b/
3ab4f5c39bcd2c194bffd9fd8abfcf2f38187083b651d50305476d5e760f9d8c7ce0f726ee59a26ee79d49e8989c94dce68009b8d9f3c1c6b466b3d74f8b0ef3   c/
Für kleine Verzeichnisse und Dateien könnt das praktikabel sein – bei größeren Datenmengen eher nicht so.
Zuletzt geändert von JTH am 11.05.2022 13:47:20, insgesamt 1-mal geändert.
Grund: --sort=name ergänzt
Manchmal bekannt als Just (another) Terminal Hacker.

Benutzeravatar
Meillo
Moderator
Beiträge: 9224
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Meillo » 11.05.2022 13:21:35

Ist denn die Reihenfolge der Dateien in einem Tarball garantiert immer identisch. Bei `find' z.B. ist sie AFAIR zufaellig. Hashwerte machen natuerlich nur Sinn wenn die Reihenfolge definiert ist.
Use ed once in a while!

JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Mehrere Verzeichnisse vergleichen

Beitrag von JTH » 11.05.2022 13:46:10

Meillo hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 13:21:35
Ist denn die Reihenfolge der Dateien in einem Tarball garantiert immer identisch.
Noch so eine philosophische Frage … :lol: So 100% ernst war mein Beitrag oben gar nicht gedacht.

Aber nein, normalerweise ist die Reihenfolge
man tar hat geschrieben:--sort=none, which stores archive members in the same order as returned by the operating system.
Das lässt sich aber anscheinend lösen mittels
man tar hat geschrieben:--sort=name ensures the member ordering in the created archive is uniform and reproducible.
Mit GNU tar zumindest. Wahrscheinlich gibts da wieder Unterschiede in Implementierungen.
Manchmal bekannt als Just (another) Terminal Hacker.

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 14:09:03

Danke euch allen, ich habe es jetzt so gelöst, in dem ich die Ausgabe von tree für jedes einzelne Verzeichnis in eine eigene Datei schreibe und dann aus diesen Dateien mit sha256sum dann eine Prüfsumme bilde:

Code: Alles auswählen

for folder in */ ; do tree $folder >>  /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; sha256sum /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; done
tree scheint die Dateien und Verzeichnisse sortiert und somit immer in gleicher Reihenfolge anzuzeigen.
tree muss AFAIK allerdings extra installiert werden, wenn es noch nicht geschehen ist, aber das mache ich bei mir immer nach jeder Debian Installation.
Meillo hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 12:57:29
Aber das haengt in erster Linie davon ab, was genau du wissen willst.
Das da:
Versuchst du also herauszufinden welche Verzeichnisse exakte Kopien voneinander sind (um die Kopien zu reduzieren)?

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 14:12:58

JTH hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 13:08:38
Meillo hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 12:57:29
Die Frage ist doch, *was* du vergleichen willst.
Unabhängig von dieser mir zum Mittag grad viel zu philosophischen Frage :mrgreen: eine ganz naive Idee: Verzeichnis(se) mit tar packen und Checksumme des Tars berechnen:
Das hätte ich natürlich auch machen können. Die Datenmenge wäre gar nicht groß gewesen, da wäre das gut gegangen.
Es ist zwar eine Brute Force Methode mit Kanonen auf Spatzen, aber hätte durchaus funktioniert.

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 14:29:02

Cordess hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 14:09:03

Code: Alles auswählen

for folder in */ ; do tree $folder >>  /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; sha256sum /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; done
Habe gerade noch einen kleinen Fehler entdeckt.
Die beiden >> Zeichen müssen durch eines ersetzt werden, falls man den Befehl mehrmals aufrufen möchte.
Macht man das nicht, dann gibt's logischerweise immer andere Hashwerte.

Also so wäre es richtig:

Code: Alles auswählen

for folder in */ ; do tree $folder >  /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; sha256sum /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; done
Das ist leider eine Angewohnheit von mir, beim Schreiben der Ausgabe in eine Datei immer doppelte > Zeichen zu verwenden.
Meistens ist es sinnvoll, aber halt nicht immer.

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 14:30:43

Wenn man dem Befehl noch ein

Code: Alles auswählen

| sort
anhängt, dann ist die Ausgabe gleich nach den Hashwerten sortiert. Das macht die Suche nach Duplikaten einfacher.

JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Mehrere Verzeichnisse vergleichen

Beitrag von JTH » 11.05.2022 14:33:04

Cordess hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 14:12:58
Es ist zwar eine Brute Force Methode mit Kanonen auf Spatzen, aber hätte durchaus funktioniert.
Ja, dann ist es tatsächlich, wie Meillo schrieb, erst einmal die Frage, was genau du vergleichen möchtest. Mit tree vergleichst du nur Vorhandensein von Dateien und Unterordnern anhand des Namens, ohne Inhalte und Berechtigungen, dafür blitzschnell; hikarus Vorschlag bezieht auch die Dateiinhalte mit ein, aber ignoriert z.B. leere Unterordner, dafür sieht man direkt die sich unterscheidenden Dateien; meine tar-Lösung fasst das zusammen und schließt auch Dateiberechtigungen ein, braucht aber entsprechend womöglich deutlich länger und liefert nur eine zusammenfassende gleich oder ungleich Aussage.
Manchmal bekannt als Just (another) Terminal Hacker.

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 15:23:16

JTH hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 14:33:04
Mit tree vergleichst du nur Vorhandensein von Dateien und Unterordnern anhand des Namens, ohne Inhalte und Berechtigungen, dafür blitzschnell;
Das ist richtig. In meinem Fall war das ausreichend.
Denn für einen groben Überblick reicht das und wenn man dann tatsächlich Verzeichnisse gefunden hat, die dann doppelt sind und
dann noch eine Unterscheidung auf Dateiinhalt usw. benötigt, dann kann man noch einmal andere Varianten nehmen. In letzterem Fall würde dann wohl auch diff selber ausreichen, da man durch die grobe Vorsortierung ja schon einmal einen Großteil der anderen Verzeichnisse aussortiert hätte.

Benutzeravatar
Meillo
Moderator
Beiträge: 9224
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Meillo » 11.05.2022 15:41:20

Cordess hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 14:30:43
Wenn man dem Befehl noch ein

Code: Alles auswählen

| sort
anhängt, dann ist die Ausgabe gleich nach den Hashwerten sortiert. Das macht die Suche nach Duplikaten einfacher.
Noch einfacher wird sie wenn man dann noch eine `uniq -d' anhaengt, weil das dann nur die Duplikate ausgibt. ;-)

Besser den Computer die Arbeit machen lassen ... gerade bei diesen sommerlichen Temperaturen! :-D
Use ed once in a while!

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 15:54:14

Meillo hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 15:41:20
Cordess hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 14:30:43
Wenn man dem Befehl noch ein

Code: Alles auswählen

| sort
anhängt, dann ist die Ausgabe gleich nach den Hashwerten sortiert. Das macht die Suche nach Duplikaten einfacher.
Noch einfacher wird sie wenn man dann noch eine `uniq -d' anhaengt, weil das dann nur die Duplikate ausgibt. ;-)

Besser den Computer die Arbeit machen lassen ... gerade bei diesen sommerlichen Temperaturen! :-D
Oh ja, stimmt natürlich. uniq -d habe ich ganz vergessen. :THX:

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 15:59:25

Jetzt habe ich doch noch einen ganz doofen Fehler in meiner tree Anweisung gefunden, was dazu führt,
dass selbst 1:1 Kopien nicht erkannt werden.

tree setzt oben ganz am Anfang der Ausgabe den Verzeichnisnamen hin. Daher kann eine Kopie mit der obigen tree Anweisung niemals gefunden werden, weil sich der oberste Verzeichnisname ja auf jeden Fall unterscheidet.

Damit das also funktioniert, müsste man die erste Zeile der tree Ausgabe entfernen, dann müsste es gehen.

EDIT:
Habe es gerade manuell getestet und die erste Zeile einfach mal mit einem Editor entfernt.
Dann funktioniert es. Das müsste man jetzt nur noch in obige tree Anweidung automatisiert einbauen.
Hat jemand Vorschläge wie man das am besten realisiert?

JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Mehrere Verzeichnisse vergleichen

Beitrag von JTH » 11.05.2022 16:04:48

Cordess hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 15:59:25
Hat jemand Vorschläge wie man das am besten realisiert?
Die Ausgabe von tree nochmal durch

Code: Alles auswählen

… | tail -n+2
schicken.
Manchmal bekannt als Just (another) Terminal Hacker.

Benutzeravatar
Meillo
Moderator
Beiträge: 9224
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Meillo » 11.05.2022 16:09:10

Code: Alles auswählen

for i in * ; do
	cd "$i"
	tree .
	cd -
done
Use ed once in a while!

Cordess
Beiträge: 422
Registriert: 09.01.2006 00:37:22

Re: Mehrere Verzeichnisse vergleichen

Beitrag von Cordess » 11.05.2022 16:10:57

JTH hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 16:04:48
Cordess hat geschrieben: ↑ zum Beitrag ↑
11.05.2022 15:59:25
Hat jemand Vorschläge wie man das am besten realisiert?
Die Ausgabe von tree nochmal durch

Code: Alles auswählen

… | tail -n+2
schicken.
Ah super, das hat bestens geklappt, hier der gesamte Befehl, falls das mal jemand braucht:

Code: Alles auswählen

for folder in */ ; do tree $folder | tail -n+2 >  /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; sha256sum /dev/shm/` echo $folder | awk -F / '{ print $1 }' ` ; done | sort
uniq -d muss man allerdings doch weglassen, weil ja der Dateiname nach dem Hash wieder unterschiedlich ist.
Man könnte zwar mit awk die Pfadangabe und den Dateinamen entfernen, aber dann hat man nur einen Hash und weiß nicht zu was der dazu gehört.

Antworten