Як порівняти частини файлів за допомогою хеша?


19

У мене один успішно завантажений файл і інша не вдалося завантажити (лише перші 100 МБ великого файлу), які, як я підозрюю, це той самий файл.

Щоб перевірити це, я хотів би перевірити їх хеші, але оскільки у мене є лише частина невдало завантаженого файлу, я хочу лише хешувати перші кілька мегабайт або близько того.

Як це зробити?

ОС буде windows, але у мене встановлені cygwin та MinGW.


1
Ефективне порівняння одного файлу на локальному комп'ютері з іншим файлом на віддаленому комп'ютері є ключовою частиною rsync , яка порівнює частини файлів із спеціальною хеш-функцією.
Девід Кері

@DavidCary У моєму випадку у мене немає доступу до оболонки до віддаленого комп'ютера, але дякую за підказку, я прочитаю сторінку
згрішив

Відповіді:


56

Створення хешів для порівняння файлів має сенс, якщо ви порівнюєте один файл проти багатьох або при порівнянні багатьох файлів один з одним.

Немає сенсу, коли порівнювати два файли лише один раз: Зусилля для обчислення хешів принаймні настільки ж великі, як перехід по файлах та їх порівняння безпосередньо.

Ефективним інструментом порівняння файлів є cmp:

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

Ви також можете комбінувати його ddдля порівняння довільних частин (не обов'язково з початку) двох файлів, наприклад:

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
Примітка: створення хешей для порівняння файлів також має сенс, якщо ви хочете уникати читання двох файлів одночасно.
Каміль Маціоровський

1
@KamilMaciorowski Так, правда. Але цей метод, як правило, буде швидшим, ніж порівняння хешей у парному випадку.
Конрад Рудольф

8
Це повне рішення. cmp99,99% напевно вже встановлено, якщо ви bashпрацюєте, і це виконує роботу. Дійсно, теж cmp -n 131072 one.zip two.zip зробить роботу. Найменше символів для набору та найшвидшого виконання. Обчислювати хеш - безглуздо. Для цього потрібно прочитати весь файл на 100 МБ, а також частину 100 МБ повного файлу, що безглуздо. Якщо вони поштові файли і вони різні, то в перші кілька сотень байт буде різниця. Тим не менш, Readahead забезпечує 128k за замовчуванням, тому ви можете також порівняти 128k (така ж вартість, як і порівняння 1 байта).
Деймон

19
Цей --bytesваріант лише ускладнює завдання. Просто запустіть cmpбез цієї опції, і він покаже вам перший байт, який відрізняється між файлами. Якщо всі байти однакові, вони відображатимуться EOFу коротшому файлі. Це дасть вам більше інформації, ніж ваш приклад - скільки байтів правильних.
пабук

2
Якщо у вас є GNU cmp(і, я думаю, що це дуже багато хто), ви можете використовувати --ignore-initialі --bytesаргументи, а не ускладнювати речі з викликами dd.
Крістофер Шульц

12

Мені шкода, що я не можу точно спробувати це, але цей спосіб спрацює

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

Ви отримаєте перші 100 мегабайт обох файлів.

Тепер дістаньте хеши:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

Ви також можете запустити його безпосередньо:

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

1
Чи є спосіб передати dd якось у sha256sum без проміжного файлу?
згрішив

1
Я додав ще один спосіб відповідно до вашого запиту
davidbaumann

8
Навіщо створювати хеші? Це набагато менш ефективно, ніж просто порівнювати фрагменти файлів безпосередньо (використовуючи cmp).
Конрад Рудольф

У своєму середньому зразку коду ви говорите first100mb1.dat двічі. Ви мали на увазі first100mb 2 .dat для другого?
doppelgreener

@KonradRudolph, "Навіщо створювати хеші?" Ваше рішення (використовуючи cmp) переможець без сумніву. Але такий спосіб вирішення проблеми (використовуючи хеши) також має право існувати до тих пір, поки він фактично вирішує проблему (:
VL-80

7

Здається, всі з цим йдуть маршрутом Unix / Linux, але порівняння двох файлів легко виконати зі стандартними командами Windows:
FC /B file file2

FC присутній у будь-якій версії Windows NT, коли-небудь зробленій. І (якщо я правильно пригадую) також був присутній у DOS.
Це трохи повільно, але це не має значення для одноразового використання.


6

Ви можете просто безпосередньо порівнювати файли з такою програмою, як бінарний / шестнадцятковий vbindiff. Він швидко порівнює файли об'ємом до 4 Гб в Linux та Windows.

Виглядає приблизно так, лише з різницею, виділеною червоним (1B проти 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     
└──────────────────────────────────────────────────────────────────────────────┘ 

У моєму випадку файли - це архіви zip, тому ніякого змістовного тексту там немає. Порівняння хеш-значень повинно бути швидшим і менш схильним до помилок.
згрішив

2
Якщо ви маєте на увазі текст ASCII, то це не має значення. vbindiff(і Конрада cmp) порівнює двійкові дані, байт за байтом. Насправді значення мають набагато більшу ймовірність зіткнення
Xen2050

* Значення "Насправді значення HASH набагато частіше трапляються зіткненнями" у коментарі, пропущеному h!
Xen2050

0

Я знаю, це говорить про Bash, але ОП також заявляє, що у них є Windows. Для всіх, хто хоче / вимагає рішення для Windows, існує програма під назвою HxD, яка є Hex Editor, яка може порівнювати два файли. Якщо файли мають різний розмір, він підкаже, чи наявні частини однакові. І якщо потрібно, він може запускати контрольні суми для того, що на даний момент вибрано. Це безкоштовно і його можна завантажити з веб-сайту HxD . Я не маю жодного зв’язку з автором (ими), я просто використовую це роками.


0

cmp скаже вам, коли два файли однакові на довжину меншого файлу:

$ 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 говорить вам, що порівняння зіткнулося з EOF у файлі a, перш ніж було виявлено різницю між двома файлами.


Влучне зауваження. Якщо ви цього ще не бачили, саме так пабук вже прокоментував прийняту відповідь.
згрішив
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.