Inhalt von Verzeichnissen anhand md5sum vergleichen

pbtraveller

Well-Known Member
Hi,

ich habe folgendes Problem:

Ich habe ein Verzeichnis-A, das in einer Vielzahl von Unterverzeichnissen eine ziemlich große Anzahl von Dokumenten beinhaltete.

Ich habe jetzt eine DVD erhalten, die angeblich die gleichen Dokumente beinhaltet. Leider ist die Verzeichnisstruktur auf der DVD ganz anders.

Beispiel: Das Dokument /Verzeichnis-A/erster_Unterordner/Beispiel.pdf ist auf der DVD unter DVD/erster_Unterordner/002_Testordner/Beispiel.pdf gespeichert. Ich muss jetzt leider bestätigen, dass ich bereits alle Dokumente die auf der DVD liegen, bereits hatte, will aber die Verzeichnisse nicht händisch durchgehen.

Ich hatte mal den md5-Hashwert aller Dateien einer DVD auf einer Linux-Kiste mit folgendem Befehl generiert:

find /DVD -type f -print0 | xargs -0 md5sum > /zielverzeichnis/checksums.txt

und so in die Datei checksums.txt geschrieben bzw. unter FreeBSD mit

find /DVD -type f -print0 | xargs -0 md5 > /zielverzeichnis/checksums.txt

Wie kann ich jetzt möglichst einfach schauen, ob alle die Dokumente mit den Hashwerten, die auch in der checksum.txt sind, auch im Verzeichnis-A liegen, ohne dass mir die unterschiedliche Verzeichnisstruktur in den Weg kommt?

In das Verzeichnis-A per cd wechseln und dann md5sum -c checksum.txt unter Linux zeigt mir nur dann OK an, wenn die Dateien im gleichen Verzeichnis liegen.

Vielen Dank für Eure Hilfe!

pbtraveller

PS. Ich habe auf der Arbeit neben windows 7 eine Linux-Maschine. Wenn Ihr aber ne Idee habt, wie ich das unter FreeBSD hinbekomme, würde ich einfach mein FreeBSD-Book mitnehmen. Bin gerade etwas verzweifelt, da das eine Unsumme von Dokumenten ist und daher eine riesige Arbeit wäre, wenn ich es von Hand machen müsste.
 

h^2

hat ne Keule +1
aus beiden hierarchien die checksums generieren (vielleicht sha256 um sicher zu sein), die namen strippen, die checksums alphabetisch sortieren und dann ein diff machen. Sollte mit awk und sort recht einfach gehen.
 

darktrym

Fahnenträger
Ich würd's ja in Python programmieren ala:
Mit einem os.walk durch die Verzeichnisstruktur
Dateinamen und Hashes in ein Dictionary

Mit einem os.walk durch die andere Verzechnisstruktur
Werte vergleichen und enfernen, Ausgabe bei Exception oder falschen Werten
--
keine 20 Zeilen, Programmieraufwand < 1h

In was für Größenordnungen befinden wir uns denn bei Anzahl und Dateigrößen?
 

Wotan

Well-Known Member
Code:
find PFAD1 -type f -print0 | xargs -0 md5sum | awk '{print $1}' | sort > checksums1
find PFAD2 -type f -print0 | xargs -0 md5sum | awk '{print $1}' | sort > checksums2
diff checksums1 checksums2
Das sollte ziemlich genau tun was h^2 vorgeschlagen hat. (FreeBSD awk kann das so mit dem print glaub ich nicht, da musst du dann gawk nehmen oder du weisst wie es dort geht)
 
Zuletzt bearbeitet:

batboy

Well-Known Member
schnell hingepfuscht in Python
Code:
d_check1 = {}
d_check2 = {}

with open("checksums1.txt") as file:
	line = file.readline()
	while line:
		words = line.split()
		d_check1[words[-1]] = words[1:-2]
		line = file.readline()

with open("checksums2.txt") as file:
	line = file.readline()
	while line:
		words = line.split()
		d_check2[words[-1]] = words[1:-2]
		line = file.readline()

for key in d_check1.keys():
	if key in d_check2:
		del d_check1[key]
		del d_check2[key]
	
for key in d_check2.keys():
	if key in d_check1:
		del d_check1[key]
		del d_check2[key]

print "nur vorhanden in checksums1.txt"
for entry in d_check1:
	print d_check1[entry]
	
print

print "nur vorhanden in checksums2.txt"
for entry in d_check2:
	print d_check2[entry]
 
Zuletzt bearbeitet:

h^2

hat ne Keule +1
Code:
find PFAD1 -type f -print0 | xargs -0 md5sum | awk '{print $1}' | sort > checksums1
find PFAD2 -type f -print0 | xargs -0 md5sum | awk '{print $1}' | sort > checksums2
diff checksums1 checksums2
Das sollte ziemlich genau tun was h^2 vorgeschlagen hat. (FreeBSD awk kann das so mit dem print glaub ich nicht, da musst du dann gawk nehmen oder du weisst wie es dort geht)
Naja, FreeBSD awk kann schon so printen, aber mit spaces im Dateinamen und überhaupt der Ausgabe ist das nicht so einfach. So gehts auch ohne awk:
Code:
find PFAD1 -type f -print0 | xargs -0 sha256 -q | sort > checksums1
find PFAD2 -type f -print0 | xargs -0 sha256 -q | sort > checksums2
diff checksums1 checksums2
 

Yamagi

Possessed With Psi Powers
Teammitglied
Das geht auch bedeutend einfacher, um den Vorschlag von gestern Abend aufzugreifen:
Code:
mtree -K sha256digest -c -p /pfad/als/vorlage | mtree -p /mit/der/vorlage/abzugleicher/pfad
Anstelle von sha256digest kann man natürlich auch eine andere Prüfsumme nehmen, die Manpage zu mtree(1) listet die Möglichkeiten auf.
 

minuseins

has spoken
Ich entschuldige mich im Vorfeld, falls ich pbtraveller missverstanden habe aber (ja jetzt kommt's)

Ich habe das so verstanden, dass pbtraveller lediglich wissen will ob alle Dateien auf der DVD auch auf dem Server liegen und das unabhaenig von der tatsaechlichen Verzeichnisstruktur. Das genannte Beispiel von pbtraveller ist aber nur ein Beispiel. Die Verzeichnisstruktur muss aber nicht unbedingt immer so um 1 verschoben sein.

@Yamagi Wenn ich mtree noch so richtig in Erinnerung habe, funktioniert mtree doch nur wenn auch die Verzeichnisstruktur lediglich verschoben ist und nicht die Dateien wild durcheinander gewuerfelt wurden.

@h^2 & @wotan

Ein diff auf die beiden Pruefsummen Dateien duerfte doch zu 100% Differenz fuehren, weil auch der Pfad hinten mit dokumentiert wurde und auf die Verzeichnisstruktur kann man sich nicht verlassen.

Da die beiden Pruefsummendateien bereits generiert wurden... was spricht gegen einen einfachen awk Einzeiler?

Code:
awk '{ if (NR==FNR) { my_array[$1]=$1; next;} if (!( $1 in my_array )) {print $0}}' <Checksumme_SERVER> <Checksumme_DVD>

Das sollte dann alle NICHT auf der DVD gefundenen Dateien anzeigen.
 

h^2

hat ne Keule +1
@h^2 & @wotan

Ein diff auf die beiden Pruefsummen Dateien duerfte doch zu 100% Differenz fuehren, weil auch der Pfad hinten mit dokumentiert wurde und auf die Verzeichnisstruktur kann man sich nicht verlassen.
Nö, da sind nur die Prüfsummen und denen ist der Pfad egal.

Da die beiden Pruefsummendateien bereits generiert wurden... was spricht gegen einen einfachen awk Einzeiler?
darum gehts doch gerade, wenn man die Prüfsummen ordentlich generiert und sortiert, dann braucht man kein awk mehr.
 

minuseins

has spoken
Nö, da sind nur die Prüfsummen und denen ist der Pfad egal.

Hast recht, ich habe das -q von sha256 uebersehen. Mea culpa.

Allerdings hat dein Ansatz 2 andere Probleme (und ein halbes):

1. Dubletten werden als Differenz angezeigt (und technisch jede Datei die auf dem Server ist, aber nicht auf der DVD)
2. Musst du dann wieder herrausfinden welche Datei dir fehlt

2.5 Hat mehr mit meiner Aversion gegen Diff zu tun, wenn es um die Weiterverarbeitung im Batch geht. Die Ausgabe ist dafuer eigentlich nicht geignet.
 
Zuletzt bearbeitet:

h^2

hat ne Keule +1
Hast recht, ich habe das -q von sha256 uebersehen. Mea culpa.

Allerdings hat dein Ansatz 2 andere Probleme (und ein halbes):

1. Dubletten werden als Differenz angezeigt
dagegen kann man ein uniq in die pipe hängen.
2. Musst du dann wieder herrausfinden welche Datei dir fehlt
Das ist ein richtiger Punkt, wenn man davon ausgeht, dass auf jeden Fall Dateien dabei sind, die man noch nicht hat, ist das nicht so praktisch. Zum Prüfen des "ob" ist es aber relativ simpel.
 

minuseins

has spoken
Was willst du mir damit sagen?

Letztlich, dass xargs hier nicht performanter ist, weil moderne find Versionen zwei -exec Varianten besitzen (Welches auch in der man dokumentiert ist und wenn man nur lesen wollte sich diese Frage selbst haette beantworten koennen)

-exec {} \; (<- man beachte das Semikolon) ist das traditionelle Verhalten, bei der find iterative ueber die Liste fuer jedes Element den entsprechenen Befehl ausfuehrt. Das fuehrt natuerlich zu einem massiven Prozessoverhead, speziell wenn bei einem md5sum es nicht selten ist, dass der Prozessstart laenger dauert als die eigentliche Berechnung des Hashes.

-exec {} \+ (<- man beachte das Plus) uebergibt die gesammelte Liste (unter der Beachtung der limits) an den entsprechenden Befehl (xargs default), weshalb man sich den kompletten init von xargs spart + erneute Uebergabe der Liste + ein paar Zeichen zum tippen.

So wie sort -u die "optimierte" Variante von sort | uniq ist, so ist hier -exec {} \+ die optimierte Variante von find | xargs. (Wobei sort | uniq bei sehr grossen Dateien sogar schneller sein kann, als sort -u und find | xargs mit -P schneller als find -exec {} \+)
 

pbtraveller

Well-Known Member
Sorry für die ultraspäte Reaktion, wollte aber doch noch meine Lösung kurz mitteilen: Ich habe es im Ergebnis ziemlich "schmutzig" gemacht.
Da ich hier leider in einer Windows-Welt arbeite und die Kollegen die Ergebnisse weiterverarbeiten müssen, habe ich die Dateien mit den Hash-Werten einer jeden DVD in Excel importiert und dort mittels eines SVERWEIS gegeneinander laufen lassen, d.h. ich habe eine Excel-Datei angelegt, in der in Spalte 1 der Hashwert zu den Dokumenten auf DVD 1 ist und in Spalte 2 der dazuehörige Pfad zu dem jeweiligen Dokument auf der DVD 1. Den Hashwert habe ich jetzt gegen ein anderes Tabellenblatt, in dem die Hashwerte der Dokumente von DVD 2 gespeichert sind, laufen lassen und habe im Falle eines "Matches" den Pfad zu dem Dokument auf DVD2 ausgeben und in Spalte 3 kopieren lassen. Blendet man nun Spalte 1 aus, so erhält man im Ergebnis eine "schöne" Liste mit zwei Spalten, in denen die Pfadangaben zu den jeweiligen Dokumenten gegenüber stehen. Der Vorteil ist außerdem, dass man die Tabelle nach beliebigen Kriterien (auch durch einen Dau) sortieren lassen kann bzw. nur einzelne Dateien ein oder ausblenden kann. Das ganze dauert, wenn man den Vorgang mal hat, keine 5 Minuten.

Dennoch vielen Dank für Eure Hilfe und Eure Ideen!

Gruß

pbtraveller
 
Oben