Gzip

如何檢查兩個 gzip 壓縮文件是否相等?

  • August 2, 2019

我試圖通過簡單地將數據轉儲到文本文件中來節省空間,同時進行“啞”備份。我的備份腳本每天執行一次,如下所示:

  1. 創建一個以備份日期命名的目錄。
  2. 將一些數據轉儲到文本文件"$name"中。
  3. 如果文件是有效的,gzip 它:gzip "$name". 否則,rm "$name"

現在,如果前一天也有相同的數據可用,我想添加一個額外的步驟來刪除文件(並創建符號連結或硬連結)。

起初我想使用md5sum "$name",但這不起作用,因為我還儲存了文件名和創建日期。

是否gzip可以選擇比較兩個 gzip 壓縮文件並告訴我它們是否相等?如果gzip沒有這樣的選擇,還有其他方法可以實現我的目標嗎?

@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

可以結合 CRC 和未壓縮的大小來獲得快速指紋:

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

CMP

要檢查兩個字節是否相等,請使用cmp file1 file2. 現在,一個 gzip 壓縮文件有一些帶有數據和頁腳(CRC 加上原始大小)的標題。gzip 格式的描述顯示,標頭包含文件壓縮的時間,並且文件名是一個以 nul 結尾的字元串,附加在 10 字節標頭之後。

因此,假設文件名是常量並且使用相同的命令( ),可以通過使用並跳過包括時間在內的第一個字節gzip "$name"來檢查兩個文件是否不同:cmp

cmp -i 8 file1 file2

注意:假設相同的壓縮選項很重要,否則該命令將始終將文件報告為不同。發生這種情況是因為壓縮選項儲存在標頭中,並且可能會影響壓縮數據。cmp只查看原始字節,不要將其解釋為 gzip。

如果您有相同長度的文件名,那麼您可以嘗試計算讀取文件名後要跳過的字節數。當文件名大小不同時,您可以cmp在跳過字節後執行,例如cmp <(cut -b9- file1) <(cut -b10- file2).

zcmp

這絕對是最好的方法,它首先壓縮數據並開始比較字節cmp(真的,這是在zcmp( zdiff) shellscript 中所做的)。

一個註釋,不要害怕手冊頁中的以下註釋:

如果在比較之前必須解壓縮兩個文件,則將第二個文件解壓縮到 /tmp。在所有其他情況下,zdiff 和 zcmp 僅使用管道。

當您擁有足夠新的 Bash 時,壓縮不會使用臨時文件,而只是使用管道。或者,正如zdiff消息來源所說:

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

引用自:https://unix.stackexchange.com/questions/64200