gzip -l -v

gzip -l -v

私は単にデータをテキストファイルにダンプし、「愚かな」バックアップを作成しながらスペースを節約したいと思います。私のバックアップスクリプトは1日1回実行され、次のようになります。

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

今後も同じデータがあった場合は、ファイルを削除する追加の手順を追加したいと思います(そしてシンボリックリンクまたはハードリンクを作成します)。

最初は使用しようとしましたが、md5sum "$name"ファイル名と作成日も保存するため、機能しません。

gzip2つの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

2バイトが同じであることを確認するには、を使用しますcmp file1 file2。 gzip圧縮ファイルには、データとフッター(CRC +ソースサイズ)が追加されたヘッダーがあります。これgzip形式の説明表示ヘッダーにはファイルが圧縮された時間が含まれ、ファイル名は10バイトヘッダーに追加されたnullで終わる文字列です。

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

cmp -i 8 file1 file2

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

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

ジカプ

これは確かに最良のアプローチです。まず、データを圧縮してバイト比較を開始します(実際にはcmp()シェルスクリプトで実行されます)。zcmpzdiff

マンページの次の説明を恐れないでください。

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

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

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

答え2

mreithubが彼のコメント(またはKevinのコマンドに似ている)が提案したようにzcmporを使用することができます。zdiffこれは、実際には2つのファイルを解凍してから、または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も安全ではありませんが、どちらも誰も壊そうとしないときに衝突防止機能があります)。 SHA-1(sha1sum)はより安全ですが遅いです。 SHA-256(sha256sum)は安全ですが、まだ遅いです。 CRC32は数倍高速ですが、長さが短く、ランダムな衝突が発生します。また、完全に安全ではありません。

答え3

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

関連情報