Как сравнить части файлов по хешу?

19

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

Чтобы проверить это, я хотел бы проверить их хэши, но, поскольку у меня есть только часть неудачно загруженного файла, я хочу хэшировать только первые несколько мегабайт или около того.

Как мне это сделать?

ОС будет Windows, но у меня установлены Cygwin и MinGW.

грешил
источник
1
Эффективное сравнение одного файла на локальном компьютере с другим файлом на удаленном компьютере является ключевой частью rsync , который сравнивает части файлов с помощью специальной хэш-функции.
Дэвид Кэри
@DavidCary В моем случае у меня нет доступа к удаленному компьютеру через оболочку, но спасибо за подсказку, я прочитаю man-страницу
согрешила

Ответы:

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
Это готовое решение. cmpна 99,99% уверен, что он уже установлен, если он bashзапущен, и он выполняет свою работу. Действительно, cmp -n 131072 one.zip two.zip тоже сделаю эту работу. Наименьшее количество символов для ввода и быстрое исполнение. Вычисление хэша бессмысленно. Требуется чтение всего файла размером 100 МБ , плюс часть файла размером 100 МБ, что бессмысленно. Если это zip-файлы и они разные, в первых нескольких сотнях байтов будет разница. Readahead предоставляет по умолчанию 128 КБ, так что вы также можете сравнить 128 КБ (такая же стоимость, как при сравнении 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 
davidbaumann
источник
1
Есть ли способ как-то направить дд в sha256sum без промежуточного файла?
согрешил
1
Я добавил другой путь по вашей просьбе
Давидбауман
8
Зачем создавать хэши? Это гораздо менее эффективно, чем просто сравнивать фрагменты файла напрямую (используя cmp).
Конрад Рудольф
В своем среднем примере кода вы говорите first100mb1.dat дважды. Вы имели в виду first100mb 2 .dat для второго?
Doppelgreener
@KonradRudolph, "Зачем создавать хэши?" Ваше решение (использование cmp) является победителем без сомнения. Но этот способ решения проблемы (с использованием хэшей) также имеет право на существование, если он действительно решает проблему (:
VL-80
7

Кажется, что все идут по пути Unix / Linux с этим, но просто сравнить 2 файла можно легко с помощью стандартных команд Windows:
FC /B file file2

ФК присутствует на всех версиях Windows NT. И (если я правильно помню) также присутствовал в DOS.
Это немного медленно, но это не имеет значения для одноразового использования.

Tonny
источник
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     
└──────────────────────────────────────────────────────────────────────────────┘ 
Xen2050
источник
В моем случае файлы представляют собой zip-архивы, поэтому никакого значимого текста там нет. Сравнение значения хеша должно быть быстрее и менее подвержено ошибкам.
согрешил
2
Если вы имеете в виду текст ASCII, то это не имеет значения. vbindiff(и Конрада cmp) сравнивает двоичные данные, байт за байт. На самом деле значения имеют гораздо большую вероятность столкновения
Xen2050
* Имеется в виду "На самом деле значения HASH гораздо чаще сталкиваются с коллизиями" в приведенном выше комментарии пропущен h!
Xen2050
0

Я знаю, что это говорит о Bash, но OP также утверждает, что у них есть Windows. Для тех, кто хочет / требует решения Windows, есть программа HxD, которая представляет собой Hex Editor, который может сравнивать два файла. Если файлы разных размеров, он скажет, совпадают ли доступные части. И если необходимо, он может запускать контрольные суммы для того, что в данный момент выбрано. Это бесплатно и может быть загружено с: веб-сайта HxD . У меня нет никакой связи с автором (ами), я просто использую это в течение многих лет.

Blerg
источник
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, прежде чем обнаружило разницу между этими двумя файлами.

Джим Л.
источник
Хорошая точка зрения. Если вы этого не видели, Пабук уже прокомментировал принятый ответ.
согрешил