如何通过哈希比较文件的各个部分?


19

我有一个下载成功的文件,另一个下载失败(大文件的前100 MB),我怀疑是同一文件。

为了验证这一点,我想检查一下它们的哈希值,但是由于我只下载了一部分失败的文件,因此我只希望对前几兆字节进行哈希处理。

我该怎么做呢?

操作系统是Windows,但是我安装了cygwin和MinGW。


1
有效地比较本地计算机上的一个文件与远程计算机上的另一个文件是rsync的关键部分,它使用特殊的哈希函数比较文件的各个部分。
大卫·卡里

@DavidCary就我而言,我没有外壳访问远程计算机的权限,但感谢您的提示,我将阅读联机帮助页
犯了罪

Answers:


56

如果将一个文件与多个文件进行比较,或者将多个文件进行相互比较,则创建散列来比较文件是有意义的。

仅一次比较两个文件没有任何意义:计算散列的工作量至少与遍历文件并直接比较它们一样高。

一个有效的文件比较工具是cmp

cmp --bytes $((100 * 1024 * 1024)) file1 file2 && echo "File fragments are identical"

您还可以将其与dd比较两个文件的任意部分(不一定从开头开始),例如:

cmp \
    <(dd if=file1 bs=100M count=1 skip=1 2>/dev/null) \
    <(dd if=file2 bs=100M count=1 skip=1 2>/dev/null) \
&& echo "File fragments are identical"

6
注意:如果要避免同时读取两个文件,则创建散列以比较文件也很有意义。
卡米尔Maciorowski

1
@KamilMaciorowski是的,是的。但是这种方法通常仍然比在成对情况下比较哈希更快。
康拉德·鲁道夫'18

8
这是待解决的方案。cmp如果您bash正在运行,则肯定已经安装了99.99%,并且可以完成此工作。确实,cmp -n 131072 one.zip two.zip 也可以完成这项工作。键入字符最少,执行速度最快。计算哈希是没有意义的。它要求读取整个100MB的文件,再加上整个文件的100MB的部分,这毫无意义。如果它们是zip文件并且不同,则前几百个字节之间会有差异。Readahead默认情况下提供128k,因此您也可以比较128k(与比较1个字节相同的成本)。
戴蒙'18

19
--bytes选项仅使任务复杂化。cmp不用此选项即可运行,它将显示文件之间不同的第一个字节。如果所有字节都相同,则它将显示EOF在较短的文件中。这将为您提供比示例更多的信息-正确的字节数。
pabouk '18

2
如果您拥有GNU cmp(而且我想几乎每个人都可以),则可以使用--ignore-initial--bytes参数,而不必将的调用复杂化dd
Christopher Schultz '18

12

抱歉,我无法完全尝试,但是这种方法可以工作

dd if=yourfile.zip of=first100mb1.dat bs=100M count=1
dd if=yourotherfile.zip of=first100mb2.dat bs=100M count=1

这将使您获得两个文件的前100 MB。

现在获取哈希:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

您也可以直接运行它:

dd if=yourfile.zip bs=100M count=1 | sha256sum 
dd if=yourotherfile.zip bs=100M count=1 | sha256sum 

1
有没有办法在没有中间文件的情况下以某种方式将dd传递到sha256sum中?
犯了罪

1
我根据您的要求添加了另一种方式
davidbaumann

8
为什么要创建哈希?与仅直接比较文件片段(使用cmp)相比,效率要低得多。
康拉德·鲁道夫'18

在您的中间代码示例中,您说了两次first100mb1.dat。您是第二个意思是first100mb 2 .dat吗?
doppelgreener

@KonradRudolph,“为什么创建哈希?” 您的解决方案(使用cmp)无疑是赢家。但是,这种解决问题的方法(使用哈希)也有权存在,只要它能够实际解决问题即可(:
VL-80

7

每个人似乎都遵循Unix / Linux的方法,但是使用Windows标准命令可以轻松地比较两个文件:
FC /B file file2

在每个Windows NT版本中都存在FC。并且(如果我没记错的话)也存在于DOS中。
它有点慢,但是一次性使用并不重要。


6

您可以使用二进制/十六进制diff程序直接比较文件vbindiff。它可以在Linux和Windows上快速比较高达4GB的文件。

看起来像这样,只是差异以红色突出显示(1B与1C):

one                                       
0000 0000: 30 5C 72 A7 1B 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....
0000 0020:
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080: 
0000 0090: 
0000 00A0: 

two        
0000 0000: 30 5C 72 A7 1C 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....               
0000 0020: 
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080:
0000 0090:                                
0000 00A0:             
┌──────────────────────────────────────────────────────────────────────────────┐
Arrow keys move  F find      RET next difference  ESC quit  T move top        
C ASCII/EBCDIC   E edit file   G goto position      Q quit  B move bottom     
└──────────────────────────────────────────────────────────────────────────────┘ 

就我而言,这些文件是zip存档,因此其中没有有意义的文本。比较散列值应该更快并且更不容易出错。
犯了罪

2
如果您的意思是ASCII文本,则无关紧要。vbindiff(和Konrad的cmp)逐字节比较二进制数据。实际上,值更容易发生冲突
Xen2050

* 上面的注释中的意思是“实际上HASH值更有可能发生冲突”,错过了h!
Xen2050

0

我知道它是针对Bash的,但是OP也声明他们有Windows。对于需要/需要Windows解决方案的任何人,都有一个名为HxD的程序,它是一个可以比较两个文件的十六进制编辑器。如果文件大小不同,它将告知可用部分是否相同。如果需要,它可以为当前选择的内容运行校验和。它是免费的,可以从以下网址下载:HxD网站。我和作者没有任何关系,我使用它已有多年了。


0

cmp会告诉您两个文件何时相同(不超过较小文件的长度):

$ dd if=/dev/random bs=8192 count=8192 > a
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.514571 secs (130417197 bytes/sec)
$ cp a b
$ dd if=/dev/random bs=8192 count=8192 >> b 
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.512228 secs (131013601 bytes/sec)
$ cmp a b
cmp: EOF on a

cmp告诉您比较在文件a上遇到EOF,然后才检测到两个文件之间的任何差异。


好点子。如果您还没有看到,这就是pabouk对已接受答案的评论。
犯罪
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.