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


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

<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

Каков самый простой способ достижения цели? Стандартный инструмент? Какой-то сторонний инструмент?

(Заметка: cmp -l должен быть убит огнем, он использует десятичную систему для смещений и восьмеричную для байтов.)


252
2018-03-29 15:28


Источник


вы в основном ищете «двоичный diff». я могу представить себе какой-то неуловимый уродливый командный лининг с одним слоем с od... - quack quixote
@quack quixote: Что уродливо об однострочном? ;) - Bobby
xdelta.org работает достаточно хорошо. Возможно, стоит взглянуть на это. - thatjuan


Ответы:


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

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'

Или сделать $1-1 чтобы первый начальный сдвиг начала отсчета был равен 0.

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1-1, strtonum(0$2), strtonum(0$3)}'

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

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)}'

Разбитый для удобочитаемости:

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)
          }'

143
2018-03-29 16:30



К сожалению, это дает мне awk: line 2: function strtonum never defined ошибки на Ubuntu 12.04. Возможно, конкретная реализация AWK? - gertvdijk
@gertvdijk: strtonum относится к GAWK. Я считаю, что Ubuntu ранее использовал GAWK в качестве значения по умолчанию, но в какой-то момент переключился на mawk, В любом случае GAWK можно установить и установить по умолчанию (см. Также man update-alternatives). См. Мой обновленный ответ для решения, которое не требует strtonum, - Dennis Williamson
Я добавил печать оригинального символа и поместил его в меню mc, мне пришлось удвоить знаки%: cmp -l %d/%f %D/%f | gawk '{printf "%%08X %%02X %%02X %%c %%c\n", $1-1, strtonum(0$2), strtonum(0$3), strtonum(0$2), strtonum(0$3)}' - 18446744073709551615


В виде ~ шарлатан указал:

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

А потом

 % diff b1.hex b2.hex

или

 % vimdiff b1.hex b2.hex

137
2018-03-29 16:07



В Баше: diff <(xxd b1) <(xxd b2) но выходной формат этого (или вашего) нигде не приближается к тому, что требует OP. - Dennis Williamson
с vimdiff он будет, он будет окрашивать байты в строках, где два «файла» отличаются - akira
Это отлично подойдет для меня (с opendiff на OS X вместо vimdiff) - вид по умолчанию xxd обеспечивает отслеживание постобработки механизма сравнения на дорожке. С простым (необработанным) шестнадцатеричным просто столбцом с fold, diff попытался бы сбросить / сгруппировать случайные вещи в файлы, которые я сравнивал. - natevw
Эта команда не работает для удаления добавления байтов, поскольку каждая последующая строка будет смещена и рассматривается как измененная diff, Решение состоит в том, чтобы поместить 1 байт на строку и удалить столбец адреса, как это было предложено Джон Лоуренс Аспден а также меня, - Ciro Santilli 新疆改造中心 六四事件 法轮功
Ваш ответ отлично подходит для небольших файлов, но не так хорошо для больших. - peterh


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

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


56
2017-09-05 21:14



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


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

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


48
2018-03-29 15:41



DHEX awesome сравнивает двоичные файлы - это то, что вы хотите сделать. Загрузите два файла, и это приведет вас к сравнительному виду, подчеркнув различия, с легкой способностью перейти к следующему различию. Также он может работать с большими терминалами, что очень полезно для широкоэкранных мониторов. - Marcin
Я предпочитаю VBinDiff. DHEX использует CPU даже на холостом ходу, я думаю, что он перерисовывает все время или что-то в этом роде. Однако VBinDiff не работает с широкими терминалами. Но адреса становятся странными с широкими терминалами, так как у вас более 16 байт в строке. - Janus Troelsen
vbindiff позволяет нам фактически редактировать файл, thx! - Aquarius Power
@DanielBeauyat сжатые файлы будут совершенно разными после того, как вы столкнетесь с первым другим байтом. Результат вряд ли будет полезен. - Mark Ransom
@ 1111161171159459134 jdiff является частью «набора» программ для синхронизации и исправления различий, обнаруженных jdiff. Но, как сказал Марк Рэнсом, это было бы вообще неразумно по сжатым файлам; исключение - это «синхронизируемые» сжатые форматы (например, созданные gzip --rsyncable), в которых небольшие различия в несжатых файлах должны иметь ограниченный эффект на сжатый файл. - hmijail


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

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 '' - - соединяется каждые две строки. Нам это нужно, потому что hex и 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

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


25
2018-04-04 20:31





Короткий ответ

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

При использовании hexdumps и text diff для сравнения двоичных файлов, особенно xxd, добавление и удаление байтов становятся смещениями в адресации, что может затруднить их просмотр. Этот метод сообщает xxd не выводить адреса и выводить только один байт на строку, что, в свою очередь, показывает, какие именно байты были изменены, добавлены или удалены. Вы можете найти адреса позже, ища интересные последовательности байтов в более «нормальном» hexdump (вывод xxd first.bin).


12
2018-04-22 12:10



(Конечно, можно использовать diff вместо vimdiff.) - VasyaNovikov


Я бы рекомендовал hexdump для сбрасывания двоичных файлов в текстовый формат и kdiff3 для просмотра diff.

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex

10
2018-06-12 07:46



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


hexdiff это программа, предназначенная для того, чтобы делать именно то, что вы ищете.

Применение:

hexdiff file1 file2

Он отображает шестнадцатеричный (и 7-разрядный ASCII) двух файлов один над другим, с любыми различиями. смотреть на man hexdiff для команд для перемещения в файле и простого q выйдет.


4
2017-10-07 04:11



Но это довольно плохо, когда дело доходит до части сравнения. Если вы вставляете некоторые байты в файл, он будет отмечать все байты впоследствии как изменения - Murmel
и hexdiff недоступен через apt-get на Ubuntu 16.4 - rubo77


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

gvim -d <(xxd -c 1 ~/file1.bin | awk '{print $2, $3}') <(xxd -c 1 ~/file2.bin | awk '{print $2, $3}')

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


3
2017-09-07 15:47