Подтвердить что ты не робот

Как использовать "cmp" для сравнения двух бинарных файлов и найти все смещения байтов, где они отличаются?

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

cmp file1 file2 

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

4b9b3361

Ответ 1

Я думаю, что cmp -l file1 file2 может делать то, что вы хотите. С manpage:

-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

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

Тогда любой вкус diff отлично работает.

Ответ 3

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

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, потому что:

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

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

  • -An удаляет столбец адресов. Это важно, иначе все строки будут отличаться после добавления/удаления байта.
  • -w1 помещает один байт в строку, так что diff может его использовать. Крайне важно иметь по одному байту в строке, иначе каждая строка после удаления перестает быть фазой и отличается. К сожалению, это не POSIX, но присутствует в GNU.
  • -tx1 - это представление, которое вы хотите, измените на любое возможное значение, если вы сохраняете 1 байт на строку.
  • -v предотвращает сокращение абзаца *, которое может помешать использованию diff
  • paste -d '' - - объединяет каждые две строки. Нам это нужно, потому что hex и ASCII переходят в отдельные смежные строки. Взято из: Объединение каждой другой строки со следующим
  • мы используем скобку () для определения bdiff вместо {}, чтобы ограничить область внутренней функции f, см. также: Как определить функцию внутри другая функция в bash

См. также: