How do I compare binary files in Linux?
I need to compare two binary files and get the output in the form:
<fileoffset-hex> <file1-byte-hex> <file2-byte-hex>
for every different byte. So if file1.bin
is
00 90 00 11
in binary form and file2.bin
is
00 91 00 10
I want to get something like
00000001 90 91
00000003 11 10
Is there a way to do this in Linux? I know about cmp -l
but it uses a decimal system for offsets and octal for bytes which I would like to avoid.
Solution 1:
This will print the offset and bytes in hex:
cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'
Or do $1-1
to have the first printed offset start at 0.
cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1-1, strtonum(0$2), strtonum(0$3)}'
Unfortunately, strtonum()
is specific to GAWK, so for other versions of awk—e.g., mawk—you will need to use an octal-to-decimal conversion function. For example,
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)}'
Broken out for readability:
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)
}'
Solution 2:
As ~quack pointed out:
% xxd b1 > b1.hex
% xxd b2 > b2.hex
And then
% diff b1.hex b2.hex
or
% vimdiff b1.hex b2.hex
Solution 3:
diff
+ xxd
Try diff
in the following combination of zsh/bash process substitution:
diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Where:
-
-y
shows you differences side-by-side (optional). -
xxd
is CLI tool to create a hexdump output of the binary file. - Add
-W200
todiff
for wider output (of 200 characters per line). - For colors, use
colordiff
as shown below.
colordiff
+ xxd
If you've colordiff
, it can colorize diff
output, e.g.:
colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)
Otherwise install via: sudo apt-get install colordiff
.
Sample output:
vimdiff
+ xxd
You can also use vimdiff
, e.g.
vimdiff <(xxd foo1.bin) <(xxd foo2.bin)
Hints:
- if files are too big, add limit (e.g.
-l1000
) for eachxxd