Как использовать «cmp» для сравнения двух двоичных файлов и найти все байтовые смещения, где они различаются? - PullRequest
27 голосов
/ 05 декабря 2011

Я бы хотел помочь с циклом скриптов Bash, который покажет все различия между двумя двоичными файлами, используя только

cmp file1 file2 

Это показывает только первое изменение, которое я хотел бы использовать cmp, потому что оно дает смещение номер строки, где находится каждое изменение, но если вы думаете, что есть лучшая команда, я открыт для нее :) спасибо

Ответы [ 3 ]

33 голосов
/ 05 декабря 2011

Я думаю cmp -l file1 file2 может делать то, что вы хотите.Из man-страницы:

-l  --verbose
      Output byte numbers and values of all differing bytes.

Выходные данные представляют собой таблицу смещения, значение байта в файле1 и значение в файле2 для всех различных байтов.Это выглядит следующим образом:

4531  66  63
4532  63  65
4533  64  67
4580  72  40
4581  40  55
[...]

Итак, первое различие по смещению 4531, где десятичное значение байта file1 равно 66, а file2 равно 63.

2 голосов

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

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 предотвращает повторение звездочки *, которое может помешать объединению diff
  • paste -d '' - - через каждые две строки.Нам это нужно, потому что гекс и ASCII идут в отдельные соседние строки.Взятые из: Конкатенируя каждую вторую строку со следующей
  • , мы используем скобку () для определения bdiff вместо {} для ограничения области действия внутренней функции f,см. также: Как определить функцию внутри другой функции в bash

См. также:

2 голосов
/ 05 декабря 2011

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

Тогда любой вариант diff будет работать нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...