Как использовать "cmp" для сравнения двух бинарных файлов и найти все смещения байтов, где они отличаются?
Мне бы очень хотелось помочь с помощью цикла Bash script, который покажет все различия между двумя двоичными файлами, используя только
cmp file1 file2
Это показывает только первое изменение, которое я хотел бы использовать cmp, потому что он дает смещение номера строки, где каждое изменение, но если вы считаете, что есть лучшая команда, я открыт для нее:) спасибо
Ответы
Ответ 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
См. также: