Jak porównać części plików według wartości skrótu?

19

Mam jeden pomyślnie pobrany plik, a drugi nieudany (tylko pierwsze 100 MB dużego pliku), który, jak podejrzewam, jest tym samym plikiem.

Aby to zweryfikować, chciałbym sprawdzić ich skróty, ale ponieważ mam tylko część nieudanego pliku, chcę hashować tylko kilka pierwszych megabajtów.

Jak mam to zrobic?

System operacyjny to Windows, ale mam zainstalowane cygwin i MinGW.

zgrzeszyli
źródło
1
Skuteczne porównywanie jednego pliku na komputerze lokalnym z innym plikiem na odległym komputerze jest kluczową częścią programu rsync , który porównuje części plików ze specjalną funkcją skrótu.
David Cary,
@DavidCary W moim przypadku nie mam dostępu do powłoki na komputerze zdalnym, ale dzięki za podpowiedź przeczytam stronę podręcznika
zgrzeszyłem

Odpowiedzi:

56

Tworzenie skrótów do porównania plików sens jeśli porównać jeden plik przeciw wielu, albo przy porównywaniu wielu plików przed sobą.

Nie ma sensu porównywanie dwóch plików tylko raz: wysiłek obliczenia skrótów jest co najmniej tak wysoki, jak przejście po plikach i porównanie ich bezpośrednio.

Skuteczne narzędzie do porównywania plików to cmp:

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

Możesz go również połączyć z, ddaby porównać dowolne części (niekoniecznie od początku) dwóch plików, np .:

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"
Konrad Rudolph
źródło
6
Uwaga: tworzenie skrótów do porównywania plików ma również sens, jeśli chcesz uniknąć czytania dwóch plików jednocześnie.
Kamil Maciorowski
1
@KamilMaciorowski Tak, prawda. Ale ta metoda nadal będzie zwykle szybsza niż porównywanie skrótów w przypadku par.
Konrad Rudolph,
8
To jest rozwiązanie na wynos. cmpma 99,99% pewności, że jest już zainstalowany, jeśli masz bashuruchomiony, i wykonuje to zadanie. Rzeczywiście, cmp -n 131072 one.zip two.zip zrobi to samo. Najmniej znaków do wpisania i najszybsze wykonanie. Obliczanie wartości skrótu jest bezsensowne. Wymaga odczytania całego pliku 100 MB, a także 100 MB części całego pliku, co jest bezcelowe. Jeśli są to pliki zip i różnią się między sobą, w pierwszych kilkuset bajtach będzie różnica. Readahead domyślnie dostarcza 128k, więc możesz także porównać 128k (taki sam koszt jak porównanie 1 bajtu).
Damon
19
Ta --bytesopcja tylko komplikuje zadanie. Po prostu uruchom cmpbez tej opcji, a wyświetli się pierwszy bajt różniący się między plikami. Jeśli wszystkie bajty są takie same, pojawi EOFsię w krótszym pliku. To da ci więcej informacji niż twój przykład - ile bajtów jest poprawnych.
pabouk
2
Jeśli masz GNU cmp(i myślę, że prawie każdy ma), można użyć --ignore-initiali --bytesargumenty zamiast komplikowania rzeczy z wywołaniami dd.
Christopher Schultz,
12

Przepraszam, że nie mogę tego dokładnie wypróbować, ale ten sposób zadziała

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

Otrzymasz pierwsze 100 megabajtów obu plików.

Teraz zdobądź skróty:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

Możesz także uruchomić go bezpośrednio:

dd if=yourfile.zip bs=100M count=1 | sha256sum 
dd if=yourotherfile.zip bs=100M count=1 | sha256sum 
davidbaumann
źródło
1
Czy istnieje sposób, aby jakoś potokować dd do sha256sum bez pliku pośredniego?
zgrzeszyło
1
Dodałem inny sposób zgodnie z twoją prośbą
davidbaumann,
8
Po co tworzyć skróty? Jest to o wiele mniej wydajne niż bezpośrednie porównywanie fragmentów plików (przy użyciu cmp).
Konrad Rudolph,
W przykładowym kodzie środkowym mówisz dwa razy: 100mb1.dat. Czy chodziło Ci o first100mb 2 .dat dla drugiego?
doppelgreener,
@KonradRudolph, „Po co tworzyć skróty?” Twoje rozwiązanie (korzystanie cmp) jest bez wątpienia zwycięzcą. Ale ten sposób rozwiązania problemu (użycie skrótów) ma również prawo istnieć tak długo, jak faktycznie rozwiązuje problem (:
VL-80
7

Wydaje się, że wszyscy podążają tą drogą Unix / Linux, ale wystarczy porównać 2 pliki za pomocą standardowych poleceń systemu Windows:
FC /B file file2

FC jest obecny we wszystkich wersjach systemu Windows NT. I (jeśli dobrze pamiętam) był również obecny w DOS.
Jest to trochę powolne, ale nie ma to znaczenia przy jednorazowym użyciu.

Tonny
źródło
6

Możesz po prostu bezpośrednio porównać pliki za pomocą programu diff binarnego / szesnastkowego vbindiff. Szybko porównuje pliki do 4 GB w systemach Linux i Windows.

Wygląda mniej więcej tak, tylko z różnicą podświetloną na czerwono (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     
└──────────────────────────────────────────────────────────────────────────────┘ 
Xen2050
źródło
W moim przypadku pliki są archiwami zip, więc nie ma tam żadnego znaczącego tekstu. Porównanie wartości skrótu powinno być szybsze i mniej podatne na błędy.
zgrzeszyło
2
Jeśli masz na myśli tekst ASCII, to nie ma to znaczenia. vbindiff(i Konrada cmp) porównuje dane binarne, bajt po bajcie. W rzeczywistości wartości są znacznie bardziej narażone na zderzenia
Xen2050
* Oznacza to, że „w rzeczywistości wartości HASH są bardziej narażone na zderzenia” w powyższym komentarzu, pominięto h!
Xen2050,
0

Wiem, że to mówi o Bash, ale OP stwierdza również, że mają Windows. Dla każdego, kto chce / wymaga rozwiązania Windows, jest program o nazwie HxD, który jest edytorem szesnastkowym, który może porównywać dwa pliki. Jeśli pliki mają różne rozmiary, pokaże, czy dostępne części są takie same. W razie potrzeby może uruchamiać sumy kontrolne dla tego, co jest obecnie wybrane. Jest bezpłatny i można go pobrać ze strony: HxD . Nie mam żadnego związku z autorem (autorami), używam go od lat.

Blerg
źródło
0

cmp powie ci, kiedy dwa pliki są identyczne do długości mniejszego pliku:

$ 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 mówi ci, że porównanie napotkało EOF w pliku a, zanim wykryło różnicę między tymi dwoma plikami.

Jim L.
źródło
Słuszna uwaga. Jeśli tego nie widziałeś, to właśnie pabouk skomentował zaakceptowaną odpowiedź.
zgrzeszyło