Wie vergleicht man Teile von Dateien nach Hash?


19

Ich habe eine erfolgreich heruntergeladene Datei und eine weitere fehlgeschlagene Datei (nur die ersten 100 MB einer großen Datei), von der ich vermute, dass es sich um dieselbe Datei handelt.

Um dies zu überprüfen, möchte ich ihre Hashes überprüfen, aber da ich nur einen Teil der nicht erfolgreich heruntergeladenen Datei habe, möchte ich nur die ersten paar Megabyte oder so hashen.

Wie mache ich das?

Betriebssystem wäre Windows, aber ich habe Cygwin und MinGW installiert.


1
Das effiziente Vergleichen einer Datei auf einem lokalen Computer mit einer anderen Datei auf einem entfernten Computer ist ein wichtiger Bestandteil von rsync , das Teile der Dateien mit einer speziellen Hash-Funktion vergleicht.
David Cary

@DavidCary In meinem Fall habe ich keinen Shell-Zugriff auf den Remotecomputer, aber danke für den Hinweis, ich werde die Manpage lesen
gesündigt

Antworten:


56

Das Erstellen von Hashes zum Vergleichen von Dateien ist sinnvoll, wenn Sie eine Datei mit mehreren Dateien vergleichen oder wenn Sie mehrere Dateien miteinander vergleichen.

Es macht keinen Sinn, zwei Dateien nur einmal zu vergleichen: Der Aufwand, die Hashes zu berechnen, ist mindestens so hoch, als wenn Sie über die Dateien gehen und sie direkt vergleichen.

Ein effizientes Dateivergleichstool ist cmp:

cmp --bytes $((100 * 1024 * 1024)) file1 file2 && echo "File fragments are identical"

Sie können es auch kombinieren dd, um beliebige Teile (nicht unbedingt von Anfang an) zweier Dateien zu vergleichen, z.

cmp \
    <(dd if=file1 bs=100M count=1 skip=1 2>/dev/null) \
    <(dd if=file2 bs=100M count=1 skip=1 2>/dev/null) \
&& echo "File fragments are identical"

6
Hinweis: Das Erstellen von Hashes zum Vergleichen von Dateien ist auch dann sinnvoll, wenn Sie vermeiden möchten, zwei Dateien gleichzeitig zu lesen.
Kamil Maciorowski

1
@KamilMaciorowski Ja, stimmt. Diese Methode ist jedoch in der Regel immer noch schneller als der Vergleich von Hashes im paarweisen Fall.
Konrad Rudolph

8
Dies ist die Lösung für unterwegs. cmpist zu 99,99% sicher, dass es bereits installiert ist, wenn Sie bashausgeführt werden, und es erledigt den Job. In der Tat cmp -n 131072 one.zip two.zip wird das auch gelingen. Wenigste Zeichen und schnellste Ausführung. Das Berechnen eines Hashs ist unsinnig. Es erfordert das Lesen der gesamten 100-MB-Datei plus eines 100-MB-Teils der gesamten Datei, was sinnlos ist. Wenn es sich um Zip-Dateien handelt und diese unterschiedlich sind, gibt es innerhalb der ersten paar hundert Bytes einen Unterschied. Readahead liefert jedoch standardmäßig 128k, sodass Sie auch 128k vergleichen können (die gleichen Kosten wie beim Vergleichen von 1 Byte).
Damon

19
Die --bytesOption erschwert nur die Aufgabe. Führen Sie einfach cmpohne diese Option aus und es wird Ihnen das erste Byte angezeigt, das sich zwischen den Dateien unterscheidet. Wenn alle Bytes gleich sind, wird dies EOFin der kürzeren Datei angezeigt. Dies gibt Ihnen mehr Informationen als in Ihrem Beispiel - wie viele Bytes sind korrekt.
Pabouk

2
Wenn Sie GNU haben cmp(und ich denke , so ziemlich jeder hat), können Sie --ignore-initialund --bytesArgumente statt Dinge mit Anrufungen zu verkomplizieren dd.
Christopher Schultz

12

Es tut mir leid, dass ich das nicht genau probieren kann, aber dieser Weg wird funktionieren

dd if=yourfile.zip of=first100mb1.dat bs=100M count=1
dd if=yourotherfile.zip of=first100mb2.dat bs=100M count=1

Dadurch erhalten Sie die ersten 100 Megabyte beider Dateien.

Holen Sie sich jetzt die Hashes:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

Sie können es auch direkt ausführen:

dd if=yourfile.zip bs=100M count=1 | sha256sum 
dd if=yourotherfile.zip bs=100M count=1 | sha256sum 

1
Gibt es eine Möglichkeit, dd ohne die Zwischendatei irgendwie in sha256sum zu leiten?
Gesündigt

1
Ich habe einen anderen Weg gemäß Ihrer Anfrage hinzugefügt
Davidbaumann

8
Warum die Hashes erstellen? Das ist viel weniger effizient als nur die Dateifragmente direkt zu vergleichen (mit cmp).
Konrad Rudolph

In Ihrem mittleren Codebeispiel sagen Sie zweimal first100mb1.dat. Meinten Sie first100mb 2 .dat für die zweite?
Doppelgreener

@KonradRudolph, "Warum die Hashes erstellen?" Ihre Lösung (mit cmp) ist ohne Zweifel ein Gewinner. Aber diese Art der Problemlösung (mit Hashes) hat auch das Recht zu existieren, solange sie das Problem tatsächlich löst (:
VL-80

7

Jeder scheint damit auf die Unix / Linux-Route zu gehen, aber mit Windows-Standardbefehlen kann man ganz einfach nur zwei Dateien vergleichen:
FC /B file file2

FC ist in jeder jemals erstellten Windows NT-Version vorhanden. Und (wenn ich mich richtig erinnere) war auch in DOS vorhanden.
Es ist ein bisschen langsam, aber das spielt für eine einmalige Verwendung keine Rolle.


6

Sie können die Dateien einfach direkt mit einem binären / hexadezimalen Diff-Programm vergleichen vbindiff. Es vergleicht schnell Dateien bis zu 4 GB unter Linux und Windows.

Sieht ungefähr so ​​aus, nur mit dem rot hervorgehobenen Unterschied (1B vs 1C):

one                                       
0000 0000: 30 5C 72 A7 1B 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....
0000 0020:
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080: 
0000 0090: 
0000 00A0: 

two        
0000 0000: 30 5C 72 A7 1C 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....               
0000 0020: 
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080:
0000 0090:                                
0000 00A0:             
┌──────────────────────────────────────────────────────────────────────────────┐
Arrow keys move  F find      RET next difference  ESC quit  T move top        
C ASCII/EBCDIC   E edit file   G goto position      Q quit  B move bottom     
└──────────────────────────────────────────────────────────────────────────────┘ 

In meinem Fall handelt es sich bei den Dateien um Zip-Archive, sodass kein aussagekräftiger Text darin enthalten ist. Das Vergleichen des Hash-Werts sollte schneller und weniger fehleranfällig sein.
Gesündigt

2
Wenn Sie ASCII-Text meinen, ist das irrelevant. vbindiff(und Konrads cmp) vergleicht binäre Daten Byte für Byte. In der Tat hat Werte sind viel wahrscheinlicher Kollisionen
Xen2050

* Gemeint „In der Tat HASH - Werte sind viel eher auf Erfahrung Kollisionen“ im obigen Kommentar, verpassten die h!
Xen2050

0

Ich weiß, dass es für Bash steht, aber OP gibt auch an, dass sie Windows haben. Für alle, die eine Windows-Lösung benötigen, gibt es ein Programm namens HxD, einen Hex-Editor, mit dem zwei Dateien verglichen werden können. Wenn die Dateien unterschiedlich groß sind, wird angezeigt, ob die verfügbaren Teile identisch sind. Bei Bedarf können Prüfsummen für alle aktuell ausgewählten Elemente ausgeführt werden. Es ist kostenlos und kann von der HxD-Website heruntergeladen werden . Ich habe keine Verbindung zu den Autoren, ich benutze es nur seit Jahren.


0

cmp teilt Ihnen mit, wann zwei Dateien bis zur Länge der kleineren Datei identisch sind:

$ dd if=/dev/random bs=8192 count=8192 > a
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.514571 secs (130417197 bytes/sec)
$ cp a b
$ dd if=/dev/random bs=8192 count=8192 >> b 
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.512228 secs (131013601 bytes/sec)
$ cmp a b
cmp: EOF on a

cmp gibt an, dass beim Vergleich eine EOF in Datei a festgestellt wurde, bevor ein Unterschied zwischen den beiden Dateien festgestellt wurde.


Guter Punkt. Wenn Sie es nicht gesehen haben, hat Pabouk die akzeptierte Antwort bereits kommentiert.
13.12.18
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.