如何检查两个 gzip 压缩文件是否相等?

Lek*_*eyn 15 gzip file-comparison

我试图通过简单地将数据转储到文本文件中来节省空间,同时进行“哑”备份。我的备份脚本每天执行一次,如下所示:

  1. 创建一个以备份日期命名的目录。
  2. 将一些数据转储到文本文件中"$name"
  3. 如果文件有效,请对其进行 gzip:gzip "$name". 否则,rm "$name"

现在我想添加一个额外的步骤来删除文件,如果相同的数据在前一天也可用(并创建符号链接或硬链接)。

起初我想使用md5sum "$name",但这不起作用,因为我还存储了文件名和创建日期。

是否gzip可以选择比较两个 gzipped 文件并告诉我它们是否相等?如果gzip没有这样的选择,还有其他方法可以实现我的目标吗?

Lek*_*eyn 14

@derobert的回答很棒,但我想分享一些我发现的其他信息。

gzip -l -v

gzip 压缩文件已经包含一个哈希值(虽然不安全,请参阅此 SO 帖子):

$ echo something > foo
$ gzip foo
$ gzip -v -l foo.gz 
method  crc     date  time           compressed        uncompressed  ratio uncompressed_name
defla 18b1f736 Feb  8 22:34                  34                  10 -20.0% foo
Run Code Online (Sandbox Code Playgroud)

可以结合 CRC 和未压缩的大小来快速获取指纹:

gzip -v -l foo.gz | awk '{print $2, $7}'
Run Code Online (Sandbox Code Playgroud)

中压

要检查两个字节是否相等,请使用cmp file1 file2. 现在,一个 gzipped 文件有一些标题,附加了数据和页脚(CRC 加上原始大小)。gzip 格式描述表明,标头包含文件被压缩的时间,并且文件名是一个以空字符结尾的字符串,附加在 10 字节的标头之后。

因此,假设文件名是常量并且使用相同的命令(gzip "$name"),可以通过使用cmp和跳过包括时间在内的第一个字节来检查两个文件是否不同:

cmp -i 8 file1 file2
Run Code Online (Sandbox Code Playgroud)

注意:假设相同的压缩选项很重要,否则该命令将始终报告文件不同。发生这种情况是因为压缩选项存储在标头中并且可能会影响压缩数据。cmp只查看原始字节而不将其解释为 gzip。

如果您有相同长度的文件名,那么您可以尝试计算读取文件名后要跳过的字节数。当文件名大小不同时,您可以cmp在跳过字节后运行,例如cmp <(cut -b9- file1) <(cut -b10- file2).

压缩包

这绝对是最好的方法,它首先压缩数据并开始比较字节cmp(实际上,这就是zcmp( zdiff) shellscript 中所做的)。

一个注意事项,不要害怕手册页中的以下注意事项:

当两个文件在比较之前都必须解压缩时,第二个文件将解压缩到 /tmp。在所有其他情况下, zdiff 和 zcmp 仅使用管道。

当你有一个足够新的 Bash 时,压缩不会使用临时文件,只是一个管道。或者,正如zdiff消息来源所说:

# Reject Solaris 8's buggy /bin/bash 2.03.
Run Code Online (Sandbox Code Playgroud)


der*_*ert 7

您可以使用zcmpzdiffmreithub 在他的评论中建议的(或 Kevin 的命令,这是类似的)。这些将相对低效,因为它们实际上解压缩了两个文件,然后将它们传递给cmpdiff。如果您只想回答“它们是否相同”,您想要cmp,它会快得多。

您使用 的md5sum方法非常好,但是您需要运行gzip. 然后将它与生成的文件一起存储在一个.gz文件中。然后,您可以在压缩文件之前轻松地比较文件。如果名称相同,md5sum -c将为您执行此操作。

$ mkdir "backup1"
$ cd backup1
$ echo "test" > backup-file
$ md5sum backup-file > backup-file.md5
$ gzip -9 backup-file
Run Code Online (Sandbox Code Playgroud)

和下一个备份:

$ mkdir "backup2"
$ cd backup2
$ echo "test" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: OK
Run Code Online (Sandbox Code Playgroud)

所以它没有改变。OTOH,有没有改变:

$ echo "different" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: FAILED
md5sum: WARNING: 1 computed checksum did NOT match
Run Code Online (Sandbox Code Playgroud)

如果你传递--quiet给它,它只会给你退出代码。0 表示匹配,非 0 表示不同。

MD5 相当快,但也不是特别快。MD4(openssl md4我相信是你在命令行上得到的最好的)大约是它的两倍(它和 MD5 都不安全,但当没有人试图颠覆它们时,两者都具有抗碰撞性)。SHA-1 ( sha1sum) 更安全,但速度较慢;SHA-256 ( sha256sum) 是安全的,但速度更慢。CRC32 应该快很多倍,但更短,因此会有更多的随机冲突。它也完全不安全。