Мне нужно сравнить два двоичных файла и получить результат в форме
<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
должен быть убит огнем, он использует десятичную систему для смещений и восьмеричную для байтов.)
Это напечатает смещение и байты в шестнадцатеричном формате:
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)
}'
В виде ~ шарлатан указал:
% xxd b1 > b1.hex
% xxd b2 > b2.hex
А потом
% diff b1.hex b2.hex
или
% vimdiff b1.hex b2.hex
Пытаться 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
Пример вывода:

Есть инструмент, называемый DHex которые могут выполнять эту работу, и есть еще один инструмент, называемый VBinDiff,
Для строго командной строки, попробуйте JDIFF,
Метод, который работает для добавления / удаления байта
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
Смотрите также:
Короткий ответ
vimdiff <(xxd -c1 -p first.bin) <(xxd -c1 -p second.bin)
При использовании hexdumps и text diff для сравнения двоичных файлов, особенно xxd
, добавление и удаление байтов становятся смещениями в адресации, что может затруднить их просмотр. Этот метод сообщает xxd не выводить адреса и выводить только один байт на строку, что, в свою очередь, показывает, какие именно байты были изменены, добавлены или удалены. Вы можете найти адреса позже, ища интересные последовательности байтов в более «нормальном» hexdump (вывод xxd first.bin
).
Я бы рекомендовал hexdump для сбрасывания двоичных файлов в текстовый формат и kdiff3 для просмотра diff.
hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex