Как сравнить двоичные файлы в Linux?

415826
bertieb

Мне нужно сравнить два двоичных файла и получить вывод в виде:

<fileoffset-hex> <file1-byte-hex> <file2-byte-hex>

за каждый другой байт. Так что, если file1.binесть

 00 90 00 11 

в двоичном виде и file2.binявляется

 00 91 00 10 

Я хочу получить что-то вроде

 00000001 90 91 00000003 11 10 

Есть ли способ сделать это в Linux? Я знаю об этом, cmp -lно он использует десятичную систему для смещений и восьмеричную для байтов, которых я хотел бы избежать.

260
вы в основном ищете "бинарный diff". я могу представить себе какой-то действительно уродливый однострочник командной строки с `od` ... quack quixote 14 лет назад 9
@ Quack Quixote: Что страшного в однострочнике? ;) Bobby 14 лет назад 2
xdelta.org работает довольно хорошо. Возможно, стоило бы взглянуть на это. thatjuan 11 лет назад 0
Потому что вы не можете ответить [на этот вопрос] (https://superuser.com/questions/125376/how-do-i-compare-binary-files-in-linux#comment1508593_983263) (так как вы не пользователь) Я голосую, чтобы закрыть. Бинарный diff, как явно запрашивается здесь, совсем не полезен, и я склонен думать, что вы хотите что-то полезное, ** если вы вставляете один байт в начале файла, все ли байты должны быть помечены как разные? ** Не зная этого, это просто слишком расплывчато. Evan Carroll 6 лет назад 0
Не говоря уже о том, что это явно противоречит правилам во многих областях, речь идет о ** «программировании и разработке программного обеспечения» **, и вы спрашиваете о продукте или рекомендации, а не о том, как * использовать * конкретный продукт. Evan Carroll 6 лет назад 0
Также обновлен метод о [radare] (https://superuser.com/a/1373977/11116), но я все еще думаю, что этот вопрос не по теме и слишком расплывчатый. Evan Carroll 6 лет назад 0
@EvanCarroll Если вы думаете, что вопрос не по теме, почему вы отвечаете на него? DavidPostill 5 лет назад 1
@ DavidPostill Я не думаю, что это не по теме. Я думаю, что это отличный вопрос. Я думаю, что это ** плохо сформулировано ** и что администраторы здесь вызовут неуместные проблемы, если я попытался бы спасти его. Смотрите мой ответ для получения дополнительной информации. Двоичный разностный вопрос? ** ДА! ** Байт для сравнения байтов? Ну, это не имеет никакого смысла в любом случае использования, который я могу себе представить. Evan Carroll 5 лет назад 0

14 ответов на вопрос

149
Dennis Williamson

Это напечатает смещение и байты в шестнадцатеричном виде:

cmp -l file1.bin file2.bin | gawk '' 

Или сделать так, $1-1чтобы первое напечатанное смещение начиналось с 0.

cmp -l file1.bin file2.bin | gawk '' 

К сожалению, strtonum()это специфично для GAWK, поэтому для других версий awk - например, mawk - вам нужно будет использовать функцию преобразования восьмеричного числа в десятичное. Например,

cmp -l file1.bin file2.bin | mawk 'function oct2dec(oct, dec) ; return dec} ' 

Вычеркнуто для удобства чтения:

cmp -l file1.bin file2.bin | mawk 'function oct2dec(oct, dec) { for (i = 1; i <= length(oct); i++) { dec *= 8; dec += substr(oct, i, 1) }; return dec } { printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3) }' 
@gertvdijk: `strtonum` относится к GAWK. Я считаю, что Ubuntu ранее использовал GAWK по умолчанию, но в какой-то момент переключился на «mawk». В любом случае GAWK может быть установлен и установлен по умолчанию (см. Также «man update-alternatives»). Смотрите мой обновленный ответ для решения, которое не требует `strtonum`. Dennis Williamson 11 лет назад 3
144
akira

Как сказал Кряк :

 % xxd b1 > b1.hex % xxd b2 > b2.hex 

А потом

 % diff b1.hex b2.hex 

или же

 % vimdiff b1.hex b2.hex 
В Bash: `diff <(xxd b1) <(xxd b2)`, но формат вывода этого (или вашего) далеко не соответствует тому, что запрашивал OP. Dennis Williamson 14 лет назад 61
с помощью vimdiff он будет окрашивать байты в строках, где два файла отличаются akira 14 лет назад 6
Ой, почему я не подумал об этом? И я уверен, что я использовал эту технику и в прошлом. njd 14 лет назад 0
Ницца. Я нахожусь на встроенной системе, которая использует BusyBox и нет `cmp`, но` hexdump` + `diff` работает как шарм. Robert Calhoun 11 лет назад 0
Это прекрасно сработало для меня (с `opendiff` на OS X вместо` vimdiff`) - представление по умолчанию `xxd` обеспечивает, что механизм сравнения отслеживает байтовые байты. При использовании простого (необработанного) шестнадцатеричного кода просто вписывающегося в столбцы с помощью `fold`,` diff` будет пытаться сворачивать / группировать случайные вещи в файлах, которые я сравнивал. natevw 10 лет назад 1
Эта команда не подходит для удаления байтов, так как каждая следующая строка будет выровнена и будет видна как измененная в `diff`. Решение состоит в том, чтобы поместить 1 байт в строку и удалить столбец адреса, как предложено [Джоном Лоуренсом Аспденом] (http://superuser.com/a/332939/128124) и [мной] (http://superuser.com/ а / 897902/128124). Ciro Santilli 新疆改造中心 六四事件 法轮功 9 лет назад 1
66
kenorb

Попробуйте diffиспользовать следующую комбинацию подстановки процесса zsh / bash и colordiffCLI:

diff -y <(xxd foo1.bin) <(xxd foo2.bin) | colordiff 

Куда:

  • -y показывает различия между собой (необязательно)
  • xxd инструмент CLI для создания вывода hexdump двоичного файла
  • colordiffбудет раскрасить diffвыход (установить через: sudo apt-get install colordiff)
  • добавить -W200к diffдля более широкого вывода

подсказки:

  • если файлы слишком большие, добавьте ограничение (например -l1000) для каждогоxxd

Образец вывода:

binary file output in terminal - diff -y <(xxd foo1.bin) <(xxd foo2.bin) | colordiff

Команду можно упростить как `colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)`. golem 9 лет назад 7
Если у вас нет colordiff, это сделает то же самое без цветов: `diff -y <(xxd foo1.bin) <(xxd foo2.bin)` Rock Lee 8 лет назад 3
Если вы просто хотите узнать, являются ли оба файла на самом деле одинаковыми, вы можете использовать ключ `-q` или` --brief`, который будет отображать вывод только тогда, когда файлы различаются. Stefan van den Akker 8 лет назад 4
создайте для этого функцию `xxddiff` с помощью:` xxddiff () (f () (xxd "$ 1";); diff -y <(f "$ 1") <(f "$ 2") | colordiff;) ` rubo77 8 лет назад 1
отличный! Тем не менее, `diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim -` хорошо поработает ribamar 6 лет назад 1
48
njd

Есть инструмент под названием DHEX, который может сделать эту работу, и есть другой инструмент, который называется VBinDiff .

Для строго командной строки попробуйте JDIFF .

DHEX потрясающе сравнивает двоичные файлы - это то, что вы хотите сделать. Подайте в него два файла, и вы перейдете прямо к сравнительному виду с выделением различий и возможностью перехода к следующему различию. Также он может работать с большими терминалами, что очень полезно на широкоэкранных мониторах. Marcin 13 лет назад 8
Я предпочитаю VBinDiff. DHEX использует процессор даже на холостом ходу, я думаю, что он постоянно перерисовывается или что-то в этом роде. VBinDiff не работает с широкими терминалами. Но адреса все равно становятся странными с широкими терминалами, так как у вас больше 16 байтов на строку. Janus Troelsen 12 лет назад 6
vbindiff позволяет нам на самом деле редактировать файл, спасибо! Aquarius Power 10 лет назад 0
+1 Но почему они говорят в jdiff -h: «Не используйте jdiff напрямую для сжатых файлов, таких как zip, gzip, rar, ...» ?? 1111161171159459134 9 лет назад 0
Сжатые файлы @DanielBeauyat будут совершенно другими после того, как вы столкнетесь с первым другим байтом. Вывод вряд ли будет полезным. Mark Ransom 9 лет назад 2
@ 1111161171159459134 jdiff является частью "набора" программ для синхронизации и исправления различий, обнаруженных jdiff. Но, как сказал Марк Рэнсом, на сжатых файлах это было бы неразумно; исключение составляют «синхронизируемые» сжатые форматы (например, созданные gzip --rsyncable), в которых небольшие различия в несжатых файлах должны оказывать ограниченное влияние на сжатый файл. hmijail 8 лет назад 2
Я был счастлив найти `vbindiff` в репозиториях Debian. Jonathon Reinhart 6 лет назад 0
`vbindiff` не может добавлять / удалять байты, только может редактировать существующий байт. 林果皞 6 лет назад 0
25
Ciro Santilli 新疆改造中心 六四事件 法轮功

Метод, который работает для добавления / удаления байтов

diff <(od -An -tx1 -w1 -v file1) \ <(od -An -tx1 -w1 -v file2) 

Сгенерируйте тестовый пример с единственным удалением байта 64:

for i in `seq 128`; do printf "%02x" "$i"; done | xxd -r -p > file1 for i in `seq 128`; do if [ "$i" -ne 64 ]; then printf "%02x" $i; fi; done | xxd -r -p > file2 

Выход:

64d63 < 40 

Если вы также хотите увидеть ASCII-версию персонажа:

bdiff() ( f() ( od -An -tx1c -w1 -v "$1" | paste -d '' - - ) diff <(f "$1") <(f "$2") )  bdiff file1 file2 

Выход:

64d63 < 40 @ 

Проверено на Ubuntu 16.04.

Я предпочитаю odболее, xxdпотому что:

  • это POSIX, xxdнет (поставляется с Vim)
  • имеет, -Anчтобы удалить адресный столбец без awk.

Объяснение команды:

  • -Anудаляет адресную колонку Это важно, иначе все строки будут отличаться после добавления / удаления байта.
  • -w1помещает один байт на строку, чтобы diff мог его использовать. Крайне важно иметь один байт на строку, иначе каждая строка после удаления окажется не в фазе и будет отличаться. К сожалению, это не POSIX, но присутствует в GNU.
  • -tx1 это представление, которое вы хотите, замените любое возможное значение, пока вы сохраняете 1 байт на строку.
  • -vпредотвращает повторение звездочки, *которое может помешать
  • paste -d '' - -соединяет каждые две строки. Нам это нужно, потому что гекс и ASCII идут в отдельные смежные строки. Взято из: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • мы используем скобки ()для определения bdiffвместо {}ограничения внутренней функции f, см. также: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Смотрите также:

13
Evgeny

Short answer

vimdiff <(xxd -c1 -p first.bin) <(xxd -c1 -p second.bin) 

When using hexdumps and text diff to compare binary files, especially xxd, the additions and removals of bytes become shifts in addressing which might make it difficult to see. This method tells xxd to not output addresses, and to output only one byte per line, which in turn shows exactly which bytes were changed, added, or removed. You can find the addresses later by searching for the interesting sequences of bytes in a more "normal" hexdump (output of xxd first.bin).

(Конечно, можно использовать `diff` вместо` vimdiff`.) VasyaNovikov 8 лет назад 0
11
BugoK

I'd recommend hexdump for dumping binary files to textual format and kdiff3 for diff viewing.

hexdump myfile1.bin > myfile1.hex hexdump myfile2.bin > myfile2.hex kdiff3 myfile1.hex myfile2.hex 
Даже здесь, в bash, `kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)` без необходимости создавать файлы `myfile1.hex` и` myfile2.hex`. Hastur 8 лет назад 2
4
Mick

The hexdiff is a program designed to do exactly what you're looking for.

Usage:

hexdiff file1 file2 

It displays the hex (and 7-bit ASCII) of the two files one above the other, with any differences highlighted. Look at man hexdiff for the commands to move around in the file, and a simple q will quit.

Но это довольно плохо работает, когда дело доходит до сравнения. Если вы вставите несколько байтов в файл, он пометит все байты как изменения Murmel 8 лет назад 4
и hexdiff недоступен через apt-get в Ubuntu 16.4 rubo77 8 лет назад 0
@ Мурмел, пока я согласен, не об этом ли здесь спрашивают? Evan Carroll 6 лет назад 0
@EvanCarroll true, и поэтому я оставил комментарий (только) и не понизил Murmel 6 лет назад 0
Я также не голосовал против Мика, но я согласен с вами и ответил здесь https://superuser.com/a/1373977/11116, потому что кажется вероятным, что этот плохой вопрос будет исправлен или закрыт. Evan Carroll 6 лет назад 0
3
John Lawrence Aspden

Возможно, он не совсем отвечает на вопрос, но я использую это для сравнения двоичных файлов:

gvim -d <(xxd -c 1 ~/file1.bin | awk '') <(xxd -c 1 ~/file2.bin | awk '') 

Он печатает оба файла как шестнадцатеричные и ASCII- значения, по одному байту на строку, а затем использует средство сравнения Vim для визуальной визуализации.

0
Vincent Vega

Dhex http://www.dettus.net/dhex/

DHEX - это не просто еще один шестнадцатеричный редактор: он включает режим diff, который можно использовать для простого и удобного сравнения двух двоичных файлов. Поскольку он основан на ncurses и является тематическим, он может работать в любом количестве систем и сценариев. Благодаря использованию поисковых журналов можно легко отслеживать изменения в разных итерациях файлов.

Добро пожаловать в SuperUser! Хотя это программное обеспечение выглядит так, будто оно * может * решить проблему ОП, в сети Stack Exchange решительно осуждается чистая реклама. Если вы связаны с редактором этого программного обеспечения, пожалуйста, сообщите об этом факте. И попробуйте переписать свой пост, чтобы он не выглядел как рекламный ролик. Спасибо. Nathan.Eilisha Shiraini 7 лет назад 0
Я никак не связан с dhex. Я скопировал описание автора в пост, потому что есть минимальный предел длины поста Vincent Vega 7 лет назад 0
Уже упоминалось по адресу: https://superuser.com/a/125390/128124. Ciro Santilli 新疆改造中心 六四事件 法轮功 7 лет назад 0

Похожие вопросы