gzip -l -v

gzip -l -v

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

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

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

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

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

答案1

@德罗伯特尽管我想分享我发现的一些其他信息,但答案很好。

gzip -l -v

gzip 压缩的文件已经包含哈希值(尽管不安全,请参阅这个帖子):

$ 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

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

gzip -v -l foo.gz | awk '{print $2, $7}'

CMP

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

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

cmp -i 8 file1 file2

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

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

兹卡普

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

请注意,不要害怕手册页中的以下注释:

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

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

# Reject Solaris 8's buggy /bin/bash 2.03.

答案2

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

你的方法md5sum非常好,但你需要采取MD5跑步gzip。然后将其与生成的文件一起存储在一个文件中.gz。然后,您可以在压缩文件之前轻松比较该文件。如果名称相同,md5sum -c将为您执行此操作。

$ mkdir "backup1"
$ cd backup1
$ echo "test" > backup-file
$ md5sum backup-file > backup-file.md5
$ gzip -9 backup-file

以及下一个备份:

$ mkdir "backup2"
$ cd backup2
$ echo "test" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: OK

所以它没有改变。 OTOH,如果它改变了:

$ echo "different" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: FAILED
md5sum: WARNING: 1 computed checksum did NOT match

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

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

答案3

要比较两个 gzip 文件,只需内容,一个命令,不diff,只是比较md5sum

$ diff -q <(zcat one.gz|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|md5sum|cut -f1 -d' ') \
    && echo same || echo not_same

您还可以“过滤”相关差异,

$ diff -q <(zcat one.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
   && echo same || echo not_same

如果编写脚本,我建议使用过滤功能(未经测试,只是一个示例),

do_filter_sum() {
  zcat $1 | grep -v '^-- Dump completed' | md5sum | cut -f1 -d' '
}

diff -q <(do_filter_sum one.gz) \
        <(do_filter_sum two.gz) \
        && echo same || echo not_same

相关内容