Come confrontare parti di file per hash?


19

Ho un file scaricato correttamente e un altro download non riuscito (solo i primi 100 MB di un file di grandi dimensioni) che sospetto sia lo stesso file.

Per verificarlo, vorrei controllare i loro hash, ma dal momento che ho solo una parte del file scaricato senza successo, voglio solo eseguire l'hashing dei primi pochi megabyte circa.

Come faccio a fare questo?

Il sistema operativo sarebbe Windows, ma ho installato cygwin e MinGW.


1
Il confronto efficiente di un file su un computer locale con un altro file su un computer distante è una parte fondamentale di rsync , che confronta parti dei file con una speciale funzione di hash.
David Cary l'

@DavidCary Nel mio caso, non ho accesso shell al computer remoto, ma grazie per il suggerimento, leggerò la manpage
peccato

Risposte:


56

La creazione di hash per confrontare i file ha senso se si confronta un file con molti o quando si confrontano molti file tra loro.

Non ha senso quando si confrontano due file una sola volta: lo sforzo di calcolare gli hash è almeno pari a quello di esaminare i file e confrontarli direttamente.

Uno strumento di confronto file efficiente è cmp:

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

Puoi anche combinarlo con ddper confrontare parti arbitrarie (non necessariamente dall'inizio) di due file, ad esempio:

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
Nota: la creazione di hash per confrontare i file ha senso anche se si desidera evitare di leggere due file contemporaneamente.
Kamil Maciorowski il

1
@KamilMaciorowski Sì, vero. Ma questo metodo sarà generalmente più veloce del confronto degli hash nel caso a coppie.
Konrad Rudolph,

8
Questa è la soluzione da seguire. cmpè sicuro che sia già installato al 99,99% se è in bashesecuzione e fa il lavoro. Anzi, cmp -n 131072 one.zip two.zip farà anche il lavoro. Il minor numero di caratteri da digitare e l'esecuzione più rapida. Il calcolo di un hash non ha senso. Richiede la lettura dell'intero file da 100 MB, più una porzione da 100 MB del file completo, il che è inutile. Se sono file zip e sono diversi, ci sarà una differenza tra le prime centinaia di byte. Readahead offre 128k di default, quindi puoi anche confrontare 128k (stesso costo del confronto di 1 byte).
Damon,

19
L' --bytesopzione sta solo complicando l'attività. Basta eseguire cmpsenza questa opzione e ti mostrerà il primo byte che differisce tra i file. Se tutti i byte sono uguali, verrà visualizzato EOFsul file più corto. Questo ti darà più informazioni del tuo esempio: quanti byte sono corretti.
pabouk,

2
Se hai GNU cmp(e, penso che quasi tutti lo facciano), puoi usare --ignore-initiale --bytesargomenti invece di complicare le cose con invocazioni di dd.
Christopher Schultz,

12

Mi dispiace di non poterlo provare esattamente, ma in questo modo funzionerà

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

Questo ti porterà i primi 100 Megabyte di entrambi i file.

Ora prendi gli hash:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

Puoi anche eseguirlo direttamente:

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

1
C'è un modo per convogliare dd in qualche modo sha256sum senza il file intermedio?
peccato dal

1
Ho aggiunto un altro modo secondo la tua richiesta
davidbaumann il

8
Perché creare gli hash? È molto meno efficiente rispetto al semplice confronto diretto dei frammenti di file (utilizzo cmp).
Konrad Rudolph,

Nell'esempio di codice centrale dici first100mb1.dat due volte. Intendevi first100mb 2 .dat per il secondo?
doppelgreener,

@KonradRudolph, "Perché creare gli hash?" La tua soluzione (usando cmp) è senza dubbio un vincitore. Ma questo modo di risolvere il problema (usando gli hash) ha anche il diritto di esistere fintanto che risolve effettivamente il problema (:
VL-80

7

Tutti sembrano seguire la rotta Unix / Linux con questo, ma basta confrontare 2 file con i comandi standard di Windows:
FC /B file file2

FC è presente su ogni versione di Windows NT mai realizzata. E (se ricordo bene) era presente anche in DOS.
È un po 'lento, ma non importa per un uso una tantum.


6

Si potrebbe semplicemente confrontare direttamente i file, con un programma diff binario / esadecimale come vbindiff. Confronta rapidamente file fino a 4 GB su Linux e Windows.

Assomiglia a questo, solo con la differenza evidenziata in rosso (1B contro 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     
└──────────────────────────────────────────────────────────────────────────────┘ 

Nel mio caso, i file sono archivi zip, quindi non contiene testo significativo. Il confronto del valore di hash dovrebbe essere più veloce e meno soggetto a errori.
peccato il

2
Se intendi il testo ASCII, è irrilevante. vbindiff(e di Konrad cmp) confronta i dati binari, byte per byte. In effetti, i valori hanno molte più probabilità di subire collisioni
Xen2050,

* Significa "In effetti i valori HASH hanno molte più probabilità di subire collisioni" nel commento sopra, ho perso la h!
Xen2050

0

So che lo dice per Bash, ma OP afferma anche che hanno Windows. Per chiunque desideri / richieda una soluzione Windows, esiste un programma chiamato HxD che è un editor esadecimale in grado di confrontare due file. Se i file hanno dimensioni diverse, indicherà se le parti disponibili sono uguali. E se necessario, è in grado di eseguire checksum per tutto ciò che è attualmente selezionato. È gratuito e può essere scaricato dal sito Web HxD . Non ho alcun collegamento con l'autore o gli autori, lo sto usando da anni.


0

cmp ti dirà quando due file sono identici fino alla lunghezza del file più piccolo:

$ 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 ti sta dicendo che il confronto ha riscontrato un EOF sul file a prima che rilevasse alcuna differenza tra i due file.


Buon punto. Se non l'hai visto, questo è ciò che pabouk ha già commentato sulla risposta accettata.
peccato dal
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.