我期望两个命令本身总是产生相同的输出,当将它们放入管道时,它们也总是产生相同的输出,但显然情况并非如此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
。
这种行为该如何解释?
答案1
生成的 gzip 文件的标头根据调用方式而不同。
Gzip 会尝试在生成的文件头中存储一些来源信息。在对普通文件调用时,默认情况下会包含来源文件名和从原始文件获取的时间戳。
当对传输到它的数据进行压缩时,其来源并不像普通文件那么简单,因此它采用不同的命名和时间戳约定。
为了证明这一点,请尝试将 -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 参数关闭的原始文件名和时间戳信息。
答案2
Gzip 文件包含时间戳。如果您在不同时间创建两个 gzip 文件,则它们的创建时间会有所不同,而内容不会有所不同。