web-dev-qa-db-ja.com

tar出力のgzipが常に異なる結果を生成するのはなぜですか?

常に同じ出力を独自に生成する2つのコマンドに期待することは、パイプラインに配置すると常に同じ出力を生成することですが、明らかにtar | gzipには当てはまりません。

~/test$ ls
~/test$ dd if=/dev/urandom of=file bs=10000000 count=1
1+0 records in
1+0 records out
10000000 bytes (10 MB) copied, 0,877671 s, 11,4 MB/s // Creating a 10MB random file
~/test$ tar cf file.tar file // Archiving the file in a tarball
~/test$ tar cf file1.tar file // Archiving the file again in another tarball
~/test$ cmp file.tar file1.tar // Comparing the two output files
~/test$ gzip -c file > file.gz // Compressing the file with gzip
~/test$ gzip -c file > file1.gz // Compressing the file again with gzip
~/test$ cmp file.gz file1.gz // Comparing the two output files
~/test$ tar c file | gzip > file.tar.gz // Archiving and compressing the file
~/test$ tar c file | gzip > file1.tar.gz // Archiving and compressing the file again
~/test$ cmp file.tar.gz file1.tar.gz // Comparing the output files
file.tar.gz file1.tar.gz differ: byte 5, line 1 // File differs at byte 5
~/test$ cmp -i 5 file.tar.gz file1.tar.gz // Comparing the output files after byte 5
~/test$ 

これに加えて、自分でtar cfz file.tar fileでも常に異なる出力を生成します。

~/test$ tar cfz file2.tar file // Archiving and compressing the file
~/test$ tar cfz file3.tar file // Archiving and compressing the file again
~/test$ cmp file2.tar.gz file3.tar.gz // Comparing the output files
file2.tar.gz file3.tar.gz differ: byte 5, line 1 // File differs at byte 5
~/test$ cmp -i 5 file2.tar.gz file3.tar.gz // Comparing the output files after byte 5
~/test$ 

パイプラインを分割すると、最終的に意味のある出力が生成されます。

~/test$ gzip -c file.tar > file4.tar.gz
~/test$ gzip -c file.tar > file5.tar.gz
~/test$ cmp file4.tar.gz file5.tar.gz 
~/test$ 

tarの出力がgzipに直接パイプされた場合にのみ、何が起こるように見えます。

この動作の説明は何ですか?

6
kos

結果のgzipファイルのヘッダーは、その呼び出し方法によって異なります。

Gzipは、結果のファイルヘッダーにいくつかのOrigin情報を保存しようとします。通常のファイルで呼び出された場合、これにはデフォルトでOriginファイル名とタイムスタンプが含まれ、元のファイルから取得されます。

パイプされたデータを圧縮する場合、Originは通常のファイルほど簡単ではないため、異なる命名規則とタイムスタンプ規則を使用します。

これを証明するために、例の問題のある行に-nパラメーターを追加してみてください...

~/temp$ tar c file | gzip -n > file1.tar.gz
~/temp$ tar c file | gzip -n > file.tar.gz
~/temp$ cmp file.tar.gz file1.tar.gz

これでファイルは再び同一になりました...

man gzipから...

   -n --no-name
          When  compressing,  do  not save the original file name and time
          stamp by default. (The original name is always saved if the name
          had  to  be  truncated.)  When decompressing, do not restore the
          original file name if present (remove only the gzip suffix  from
          the  compressed  file name) and do not restore the original time
          stamp if present (copy it from the compressed file). This option
          is the default when decompressing.

そのため、実際の違いは、元のファイル名と-nパラメーターによってオフにされるタイムスタンプ情報です。

9
Clayton Mills

Gzipファイルにはタイムスタンプが含まれます。 2つのgzipファイルを異なる時間に作成する場合、これらはコンテンツではなく作成時間によって異なります。

5