如何使用“cmp”来比较两个二进制文件并找到它们不同的所有字节偏移量?

时间:2011-12-05 12:53:59

标签: bash shell unix

我希望得到一些Bash脚本循环的帮助,它将显示两个二进制文件之间的所有差异,仅使用

cmp file1 file2 

它只显示了我想要使用cmp的第一个更改,因为它给出了一个偏移量,每个更改的行数,但是如果你认为有一个更好的命令,我会对它开放:)谢谢

3 个答案:

答案 0 :(得分:33)

我认为cmp -l file1 file2可能会做你想要的。从联机帮助页:

-l  --verbose
      Output byte numbers and values of all differing bytes.

输出是偏移量表,file1中的字节值和file2中所有不同字节的值。它看起来像这样:

4531  66  63
4532  63  65
4533  64  67
4580  72  40
4581  40  55
[...]

所以第一个区别在于偏移4531,其中file1的十进制字节值为66,file2' s为63。

答案 1 :(得分:2)

我发现更有效的解决方法是使用od将二进制文件转换为某种形式的文本。

然后diff的任何风格都可以。

答案 2 :(得分:2)

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

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因为:

  • is POSIXxxd不是(Vim附带)
  • -An删除没有awk的地址列。

命令解释:

  • -An删除地址列。这很重要,否则所有行在添加/删除字节后都会有所不同。
  • -w1每行放一个字节,以便diff可以使用它。每行一个字节至关重要,否则删除后的每一行都会变得异相并且不同。不幸的是,这不是POSIX,而是存在于GNU中。
  • -tx1是您想要的表示,只要每行保留1个字节,就可以更改为任何可能的值。
  • -v会阻止可能干扰差异的星号重复缩写*
  • paste -d '' - -每两行加入一次。我们需要它,因为十六进制和ASCII进入单独的相邻行。取自:Concatenating every other line with the next
  • 我们使用括号()来定义bdiff而不是{}来限制内部函数f的范围,另请参阅:How to define a function inside another function in bash

另见: