2つのgzip圧縮ファイルが等しいかどうかを確認するにはどうすればよいですか?


11

データをテキストファイルにダンプするだけで、「ダム」バックアップを実行しながらスペースを節約しようとしています。私のバックアップスクリプトは毎日実行され、次のようになります。

  1. バックアップ日付にちなんだ名前のディレクトリを作成します。
  2. 一部のデータをテキストファイルにダンプします"$name"
  3. ファイルが有効な場合は、gzipしてくださいgzip "$name"。それ以外の場合は、rm "$name"

同じデータが前日に利用可能であった場合(およびシンボリックリンクまたはハードリンクを作成した場合)、ファイルを削除するための追加ステップを追加したいと思います。

最初はを使用することを考えましたがmd5sum "$name"、ファイル名と作成日も保存しているため、これは機能しません。

gzip2つのgzip圧縮ファイルを比較して、それらが等しいかどうかを確認するオプションはありますか?そのgzipようなオプションがない場合、私の目標を達成する別の方法はありますか?


1
これを試してください:linux.die.net/man/1/zdiff
mreithub

2
私はを提案するつもりでしたdiff <(zcat file1) <(zcat file2)が、mrethubのzdiffルックスの提案ははるかに優れています。
ケビン

backuppcは、手動で達成しようとしていることを実行します
drone.ah

@ drohne.ah backuppcは、1日1ファイルだけの場合は、やり過ぎかもしれません...(gzipにかなり意味のあるSQLダンプのようなものです)
mreithub

1
@mdpc MD5のアルゴリズムの問​​題はおそらく関係ありません。衝突を構築することは可能ですが、おそらく唯一の懸念は、攻撃者ではなく偶然に発生したものです。そして、それはあなたが2〜64個のファイルを手に入れるまでまだ起こりそうにありません。プリイメージ攻撃でさえ、おそらく問題ではありません。
derobert 2013

回答:


7

zcmpまたはzdiff、mreithubが彼のコメント(または同様のKevinのコマンド)で示唆しているように使用できます。これらは実際には両方のファイルを解凍してからcmpまたはに渡すため、比較的非効率的diffです。「同じですか」と答えたいだけの場合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あなたがコマンドラインで得る最高のものだと私は信じています)は約2倍の速さです(MD5もMD5も安全ではありませんが、どちらもだれもそれらを破壊しようとしないときの衝突耐性と同じくらいです)。SHA-1(sha1sum)はより安全ですが低速です。SHA-256(sha256sum)は安全ですが、さらに遅くなります。CRC32は何倍も速くなるはずですが、短くなるため、ランダムな衝突が多くなります。また、完全に安全ではありません。


zdiffファイルが変更されたかどうかではなく、ファイルが変更されたかどうかを知りたいだけなので、もったいないようです。zcmpおもしろそうです、試してみます。
Lekensteyn 2013

7

@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

2バイトが等しいかどうかを確認するには、を使用しますcmp file1 file2。これで、gzip圧縮されたファイルには、データとフッター(CRCと元のサイズ)が追加されたヘッダーが追加されました。gzip形式説明は、ヘッダーにファイルが圧縮された時刻が含まれていること、およびファイル名が10バイトのヘッダーの後に追加されるNUL終了ストリングであることを示しています。

したがって、ファイル名が一定で同じコマンド(gzip "$name")が使用されていると仮定するcmpと、時間を含む最初のバイトを使用してスキップすることで、2つのファイルが異なるかどうかを確認できます。

cmp -i 8 file1 file2

:同じ圧縮オプションが重要であるという前提です。そうでない場合、コマンドは常にファイルを異なるものとして報告します。これは、圧縮オプションがヘッダーに格納されており、圧縮データに影響を与える可能性があるために発生します。cmp生のバイトだけを見て、それをgzipとして解釈しません。

同じ長さのファイル名がある場合、ファイル名を読み取った後にスキップされるバイトを計算することができます。ファイル名のサイズが異なる場合cmp、などのバイトをスキップして実行できますcmp <(cut -b9- file1) <(cut -b10- file2)

zcmp

これは間違いなく最善の方法です。最初にデータを圧縮し、バイトとの比較を開始しますcmp(実際、これはzcmpzdiff)シェルスクリプトで行われます)。

1つの注意点として、マニュアルページにある次の注意点を恐れないでください。

比較する前に両方のファイルを解凍する必要がある場合、2番目のファイルは/ tmpに解凍されます。他のすべての場合では、zdiffとzcmpはパイプのみを使用します。

十分に新しいBashがある場合、圧縮では一時ファイルは使用されず、パイプのみが使用されます。または、zdiffソースが言うように:

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

バイト4(FLG)が0の場合、ファイル名はヘッダーにないので、その長さを気にする必要はありません。また、gzip -v -lヘッダーの4つのMTIMEバイトがゼロの場合、MTIMEではなくファイル時間を報告することがわかりました。また、MTIMEが存在する場合は、圧縮が開始された時刻であるため、通常はファイル時刻の少し前にあることに注意してください。
キチン

0

2つのgzipファイルを比較するには、内容のみ、1つのコマンド、いいえ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

md5sumは無駄ですcmp。使用できます。zcatおよびgrepにマージできますzgrep
Lekensteyn 2013年

true、md5sumは比較する必要はありません(すでに生成されている場合を除く)。デロベルトが使ったので使ったばかりです。zgrepは、基本的にはgunzipとgrep(または場合によってはsed)を実行するだけのスクリプトなので、そこにはほとんど違いがありません。投稿されたスクリプトは、プラグ可能なパーツを備えたパイプのチェーンとして意図的に示されています。すべてを1つのコマンドにマージする楽しみは何ですか?
マイケル

1
そしてzcatただgunzip -cです。適切なツールを適切な仕事に使用してください。KISSは肥大化よりも優れています。この場合、必要に応じてハードリンクを生成するものを書くことに時間を費やします。
Lekensteyn 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.