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


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 

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.
Это немного медленно, но это не имеет значения для одноразового использования.


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, но OP также утверждает, что у них есть 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.