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

lew*_*nny 29 unix bash shell

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

cmp file1 file2 
Run Code Online (Sandbox Code Playgroud)

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

rwo*_*wos 34

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

-l  --verbose
      Output byte numbers and values of all differing bytes.
Run Code Online (Sandbox Code Playgroud)

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

4531  66  63
4532  63  65
4533  64  67
4580  72  40
4581  40  55
[...]
Run Code Online (Sandbox Code Playgroud)

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

  • +1:这是'做到这一点的方法',但问题是'cmp`不会寻找插入或删除的材料; 它只是检查'file1中偏移量N处的字节是否与file2中偏移量N处的字节相同; 如果是,则不打印,否则打印差异'.所以这些文件必须非常相似(例如,在编译目标文件时,Unix时间戳中只有一些字节 - 内置于某些目标文件中),但其余部分必须相同.将3个字节添加到常量字符串,之后的所有内容都不同. (3认同)
  • 我通过添加有关不同字节格式的更正来编辑答案。这是 cmp 的一个没有详细记录的功能。我希望编辑是适当的。 (2认同)

Cir*_*四事件 5

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

diff <(od -An -tx1 -w1 -v file1) \
     <(od -An -tx1 -w1 -v file2)
Run Code Online (Sandbox Code Playgroud)

生成一个单次删除字节 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
Run Code Online (Sandbox Code Playgroud)

输出:

64d63
<  40
Run Code Online (Sandbox Code Playgroud)

如果您还想查看字符的 ASCII 版本:

bdiff() (
  f() (
    od -An -tx1c -w1 -v "$1" | paste -d '' - -
  )
  diff <(f "$1") <(f "$2")
)

bdiff file1 file2
Run Code Online (Sandbox Code Playgroud)

输出:

64d63
<   40   @
Run Code Online (Sandbox Code Playgroud)

在 Ubuntu 16.04 上测试。

我喜欢odxxd,因为:

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

命令解释:

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

也可以看看: