如何在 Linux 中比较二进制文件?

如何在 Linux 中比较二进制文件?

我需要比较两个二进制文件并以以下形式获取输出

<文件偏移量十六进制> <文件 1 字节十六进制> <文件 2 字节十六进制>

对于每个不同的字节。因此file1.bin如果

  00 90 00 11

二进制file2.bin形式

  00 91 00 10

我想要得到类似的东西

  00000001 90 91
  00000003 11 10

在 Linux 中有没有办法做到这一点?我知道cmp -l但是它使用十进制系统表示偏移量,使用八进制系统表示字节,这是我想避免的。

答案1

这将以十六进制打印偏移量和字节:

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)
          }'

答案2

作为~嘎嘎指出:

 % xxd b1 > b1.hex
 % xxd b2 > b2.hex

进而

 % diff b1.hex b2.hex

或者

 % vimdiff b1.hex b2.hex

答案3

diff+xxd

尝试diff在以下 zsh/bash 组合中进行进程替换:

diff -y <(xxd foo1.bin) <(xxd foo2.bin)

在哪里:

  • -y并排显示差异(可选)。
  • xxd是用于创建二进制文件的十六进制转储输出的 CLI 工具。
  • 添加-W200diff获得更宽的输出(每行 200 个字符)。
  • 对于颜色,请colordiff按如下所示使用。

colordiff+xxd

如果你有colordiff,它可以为输出着色diff,例如:

colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)

否则通过以下方式安装:sudo apt-get install colordiff

示例输出:

终端中的二进制文件输出 - diff -y <(xxd foo1.bin) <(xxd foo2.bin) | colordiff

vimdiff+xxd

您还可以使用vimdiff,例如

vimdiff <(xxd foo1.bin) <(xxd foo2.bin)

提示:

  • 如果文件太大,-l1000则为每个文件添加限制(例如)xxd

答案4

diff+od适用于字节添加/删除的方法

diff <(od -An -tx1 -w1 -v file1) \
     <(od -An -tx1 -w1 -v file2)

你可能想在 Bash 中将其别名为:

bdiff() {
  diff <(od -An -tx1 -w1 -v "$1") \
       <(od -An -tx1 -w1 -v "$2")
}

生成一个删除第 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,因为:

  • 是 POSIXxxd不是(Vim 自带)
  • -An删除地址栏的权限,无需awk

命令解释:

也可以看看:

相关内容