Почему gzip при выводе tar всегда дает разные результаты?
Что я ожидаю от двух команд, которые всегда выдают один и тот же вывод самостоятельно, так это от того, что они всегда выдают один и тот же вывод при помещении в конвейер, но, очевидно, это не так 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
,
Чем объясняется такое поведение?
2 ответа
Заголовок полученного файла 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.
Gzip файлы содержат метку времени. Если вы создаете два файла gzip в разное время, они будут отличаться временем создания, а не содержимым.