Ce que j'attends de deux commandes qui produisent toujours la même sortie, c'est qu'elles produisent toujours la même sortie lorsqu'elles sont placées dans un pipeline, mais ce n'est apparemment pas le cas pour 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$
Ajoutant à cela, même tar cfz file.tar file
produit à lui seul différentes sorties:
~/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$
Lorsque vous séparez le pipeline, vous obtenez une sortie qui a du sens:
~/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$
Il semble que tout ce qui se passe ne se produit que lorsque la sortie de tar
est acheminée directement dans gzip
.
Quelle est l'explication de ce comportement?
L'en-tête du fichier gzip obtenu est différent selon son appel.
Gzip essaie de stocker des informations sur l'origine dans l'en-tête du fichier résultant. Lorsqu'il est appelé sur des fichiers normaux, cela inclut le nom du fichier d'origine par défaut et un horodatage, qu'il récupère à partir du fichier d'origine.
Lorsqu'il est conçu pour compresser les données qui y sont acheminées, l'Origin n'est pas aussi facile qu'avec un fichier normal. Il a donc recours à une convention de dénomination et d'horodatage différente.
Pour le prouver, essayez d'ajouter le paramètre -n aux lignes incriminées de votre exemple en tant que ...
~/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
Maintenant les fichiers sont à nouveau identiques ...
De 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.
La différence est donc bien le nom de fichier d'origine et les informations d'horodatage désactivées par le paramètre -n.
Les fichiers Gzip incluent un horodatage. Si vous créez deux fichiers gzip à des moments différents, ceux-ci seront différents en fonction de la date de création et non du contenu.