Grimoire-
Command
.es

GNU+Linux command memo

Memo_8 : Archives, compression et décompression de fichiers

D’après l’édition 11 des travaux d’Alain Leaper, 2018-04-10
Licence GPL

1. Introduction

Il est possible de réduire la taille (en octets) de la plupart des fichiers informatiques, sans rien perdre de leur contenu. Cette opération est connue sous le nom de compression de fichier. Une forme simple de compression de fichier consiste à chercher des portions de fichier identiques, à noter leur emplacement, et à ne garder qu’une des occurrences de cette portion de fichier. C’est le principe de la factorisation en mathématique.

Le fichier ainsi obtenu occupe moins de place sur le disque dur, et est plus rapide à recopier sur le réseau.

La compression de fichiers est souvent liée à un autre principe simple, la création d’archives. Une archive est ici un fichier regroupant le contenu de plusieurs autres fichiers. La forme basique consiste à coller le contenu de plusieurs fichiers à la suite dans un seul nouveau fichier cible. On obtient alors un nouveau gros fichier, plus rapide à recopier (à graver, à déplacer) qu’une série de petits fichiers, car le temps passé à faire les vérifications (notamment celle de place disponible sur le support cible d’une copie) n’est perdu qu’une fois pour l’archive, alors qu’il l’aurait été pour chaque petit fichier sinon. On factorise ici ce qui se passe avant et après la copie d’un fichier, pour ne garder que le temps de la copie elle-même.

Toutefois, si on ne copie que le contenu des fichiers à la suite les uns des autres, on perd les noms de ces fichiers, ainsi que leurs permissions… et il faut bien noter leur taille quelque part pour pouvoir les séparer ensuite. On utilise donc des logiciels spécialisés pour faire ça proprement.

Une fois notre archive créée, puisqu’on a réalisé une tâche répétitive, on a probablement créé des répétitions dans le contenu de notre fichier archive. Et puis ce dernier pourrait contenir plusieurs copies de fichiers très ressemblant (comme plusieurs version d’une lettre ou d’un code source). On associe donc généralement l’agglutination de fichiers en archive, avec la compression de fichier.

On obtient alors des archives comprimées, doublement pratiques et rapides à copier.

Dans ce mémo, nous allons voir les commandes permettant de gérer les principaux formats de compression de fichier, puis nous verrons le couteau suisse du domaine chez GNU+Linux : tar.

2. Outils de compression / décompression de fichiers : GZip, BZip2 et XZ

Le format zlib mis en œuvre par l’utilitaire gzip est un format historique du monde Unix. Il est encore largement utilisé aujourd’hui (notamment pour ce qui est du transfert des pages web, qui vous arrivent le plus souvent compressées), car il est extrêmement rapide en ce qui concerne le temps de compression et de décompression.

Le format bzip2 est lui une évolution cherchant à obtenir des fichiers plus petits en consacrant plus de temps aux astuces mises en place pour obtenir un fichier plus petit.

De nombreuses autres alternatives ont été développées, et elles sont minutieusement comparées entre elles en fonction de critères comme : le temps de compression, celui de décompression, la quantité de mémoire RAM utilisée pour ces opérations, ou encore l’efficacité de la compression.

Le format xz est actuellement le plus complémentaire du gzip. En effet le xz a été conçu pour être "le plus efficace possible" dans la compression obtenue, sans négliger la vitesse de décompression (tout en utilisant peu de mémoire RAM). Il est donc logiquement lent et gourmand en RAM à la compression. Ces choix ont été fait en tenant compte du fait qu’on peut être amené à décompresser plusieurs fois une archives après sa création (il semble donc plus intéressant d’optimiser le temps de décompression). Techniquement, xz est une implémentation de l’algorithme de compression LZMA (introduit par le format de fichier .7z) et même d’une amélioration de ce format nommée LZMA2 (tous deux à base de chaînes de Markov cachées). L’utilitaire xz, contrairement à 7z est conçu pour remplacer facilement gzip ou bzip2 en supportant la même syntaxe et les mêmes options.

Un dernier format vient d’arriver à grand bruit dans les distributions GNU/Linux, il s’agit du Zstandard (.zst) qui mise tout sur la vitesse de décompression, en se contentant d’atteindre des compressions comparables au zlib. Il est finement configurable dans son équilibre entre vitesse de traitement et taux de compression et a notamment été adopté par Arch Linux pour compresser les paquets de la distribution. Ce choix a été motivé par les vitesses de décompression atteintes par Zstandard, 4 à 6 fois supérieures au zlib. La différence s’apprécie à chaque installation, le temps de traitement post-téléchargement ayant presque disparu grâce à un format capable de décompresser des giga-octets de données par seconde, que les périphériques de stockage modernes, de type NVME sont en plus capable d’encaisser en écriture !

Enfin, terminons par un tour d’horizon des algorithmes de compression spécifiques pour un type de fichier donné :

  • compression de la musique, en FLAC (proche d’un .wav "GZippé") ou avec pertes d’une partie jugée négligeable des données en MP3 (qui supprime la partie normalement inaudible des sons car trop grave ou aiguë et les blancs) ;

  • compression des images en PNG (proche d’un bitmap "GZippé"), ou avec perte de qualité en GIF ou JPEG qui conservent moins de couleurs donnant un résultat plus terne ou des dégradés en escalier ;

  • compression des vidéos : GIF animé, MPEG, MP4, H.264, H.265 (tout est avec perte de qualité dans la compression, une seconde de vidéo représentant autour de 25 images, la question de l’efficacité de la compression est apparue très vite dans ce domaine…) ;

  • ou encore les fichiers de bureautique, nativement compressés en GZip par leur éditeur, notamment le format OpenDocument (.odt) de LibreOffice.

La commande pour comprimer un fichier est de la forme :

$ cmd -options nomDeFichier
$ gzip monFichier (1)
$ bzip2 monFichier (2)
$ xz monFichier (3)
1 monFichier est remplacé par monFichier.gz
2 monFichier est remplacé par monFichier.bz2
3 monFichier est remplacé par monFichier.xz

L’option -9 de gzip permet d’indiquer qu’on souhaite passer plus de temps à tenter de comprimer d’avantage le fichier. La compression qui en résulte est généralement un peu plus importante. La commande xz comprime de son mieux dès le début et vous aurez le temps de vous en souvenir, vu qu’elle consomme également beaucoup de ressources système ce faisant.

$ gzip -9 monFichier (1)
1 donne une taille plus faible pour monFichier.gz, mais prends un peu plus de temps.

Remarque : contrairement à ce à quoi on pourrait s’attendre, la compression avec bzip2 n’est pas toujours meilleure que celle obtenue par gzip. Il peut également arriver qu’XZ ne soit pas vraiment meilleur que gzip. C’est notamment le cas des fichiers présentant de grosses similitudes faciles à trouver. Mais ce n’est pas toujours évident à anticiper.

L’option -c (de gzip ou bzip2) permet d’utiliser le canal de sortie standard, et donc de le rediriger :

$ gzip -c monFichier > autreFichier.gz (1)
1 monFichier est conservé

L’option -d (gzip ou bzip2) permet de décompresser un fichier compressé précédemment par le même utilitaire.

$ bzip2 -d monFichier.bz2

Remarque :

gzip -d monFichier.gz peut être remplacé par : gunzip monFichier.gz

bzip2 -d monFichier.bz2 peut être remplacé par : bunzip2 monFichier.bz2

xz -d monFichier.xz peut être remplacé par : unxz monFichier.bz2

3. tar : gestion d’archives

Le nom vient des archives sauvegardées sur bandes magnétiques : tape archives.

3.1. Forme générale (-c)

$ tar -cvf nomArchive.tar fichier_0 fichier_1 fichier_2 …
  • fichier_0 fichier_1… sont les fichiers à mettre dans l’archive nomArchive.tar

  • * est utilisable : exemple tar -cf nomArchive.tar ./fich*

  • les répertoires et leurs sous-répertoires sont archivés jusqu’à atteindre les fichiers.

  • la structure de l’archive dépend de la manière dont le répertoire de "départ" est spécifié : si le chemin complet est indiqué, celui-ci sera retrouvé à l’extraction.

  • -c (creation) demande la création d’un fichier d’archive.

  • -f (file) : désigne le nom du fichier archive, cette option est quasiment obligatoire !

Bien que cela ne soit pas obligatoire, et puisque ce n’est pas automatique, notons qu’il est préférable de spécifier une extension .tar pour le nom des fichiers d’archive.
  • -v (verbose) : mode "verbeux", affiche, en cours d’opération, la liste des fichiers traités. -vv donnerait encore plus d’infos…

3.2. Extraire les fichiers / répertoires composant une archive : option -x

$ tar -xvf nomArchive.tar (1)
$ tar -xvf nomArchive.tar nomComposant (2)
1 extraction de la totalité des composants
2 extraction d’un composant particulier : fichier ou répertoire
nomComposant doit être le nom complet (c-à-d avec le chemin) tel qu’il apparaît dans l’archive : tar -tvf nomArchive.tar pour connaître ce nom.

3.3. Ajout d’un (ou plusieurs) fichier(s) à une archive existante : option -r

$ tar -rvf nomArchive.tar nouveauFichier (1)
1 ajoute nouveauFichier dans nomArchive.tar
Cette opération n’est pas possible sur une archive compressée.

3.4. Voir le contenu d’une archive : option -t

$ tar -tvf nomArchive.tar

Il est important de prendre connaissance de la structure d’une archive avant de décider dans quel répertoire doit se dérouler l’extraction. Par exemple si l’archives contient directement un grand nombre de fichiers, il peut sembler préférable de créer d’abord un dossier où décompresser l’archive sans perdre la trace des fichiers décompressés, s’ils sont déjà dans un dossier dans l’archive la précaution est inutile.

3.5. Stratégie pour la création / extraction d’archives afin de garder la même arborescence

  • Si le chemin absolu (c-à-d à partir de la racine /) a été spécifié lors de la création, alors pour l’extraction, se mettre sous la racine (/).

  • Si un chemin relatif, à partir du répertoire courant a été spécifié lors de la création : tar -cvf nomArchive.tar ./* Alors pour l’extraction, créer si nécessaire, et se placer dans le répertoire désiré.

  • Si un chemin relatif à partir du répertoire parent (de celui à archiver) a été spécifié lors de la création : tar -cvf nomArchive.tar ./repertoireFils Alors pour l’extraction se placer dans ce répertoire parent.

Exemple : archiver le répertoire de travail de l’utilisateur pierre (/home/pierre)

$ cd /home
$ tar -cvf pierreArchi.tar ./pierre
$ cd /home (1)
$ tar -xvf pierreArchi.tar
1 À l’extraction (par exemple sur une autre station)

Il existe l’option -C pour changer le répertoire destination.

$ tar -C repDesti -xcf /chemin/nomArchive.tar

Va extraire l’archive dans repDesti (au lieu du répertoire courant). Cette option est très pratique, en particulier lorsque l’on doit repartir de la racine (ou d’un niveau "élevé" dont on n’est pas propriétaire) pour extraire dans un niveau dont on possède les droits d’accès en écriture.

  • tar n’est pas "ré-entrant" : il n’y a pas de problème pour créer une archive à partir du répertoire courant en sélectionnant tous les fichiers :

$ tar -cvf nomArchive.tar ./* (1)
1 ne créer pas boucle, pas d’auto archivage récursif de nomArchive.tar

Il est possible de créer l’archive dans un répertoire autre que dans le répertoire courant :

$ tar -cvf ~/mesAchives/ceRepertoire.tar ./*

3.6. Création / extraction d’archives compressées

Plutôt que de compresser les fichiers puis de les archiver, ou d’archiver puis de compresser l’archive, il est plus commode de procéder en une seule opération :

  • -z compression / décompression par gzip

tar -zcvf nomArchive.tar.gz *
tar -zxvf nomArchive.tar.gz
  • -j compression / décompression par bzip2

tar -jcvf nomArchive.tar.bz2 *
tar -jxvf nomArchive.tar.bz2
  • -J compression / décompression par xz

tar -Jcvf nomArchive.tar.xz *
tar -Jxvf nomArchive.tar.xz

Remarques :

  • bien que l’extension .tar.gz ne soit pas obligatoire, elle est recommandée, en cas de doute la commande file nomArchive indique la nature du fichier

  • l’ordre des options n’est pas fixe, excepté pour l’option -f qui doit être suivie du nom du fichier ciblé. De plus -v est facultatif, l’enlever rend juste la commande moins bavarde. Ainsi on peut décompresser une archive avec : tar -xJf nomArchive.tar.xz

  • pour voir la composition de l’archive l’option -z (ou -j, ou -J) n’est pas indispensable tar -tvf nomArchive.tar.bz2 idem tar -jtvf nomArchive.tar.bz2

  • il n’est pas possible de faire un ajout dans une archive compressée, impossible : tar -r

  • le canal d’entrée standard de tar peut être impliqué par le signe -. Certains auteurs utilisent cette possibilité, comme ci-dessous : $ zcat nomArchive.tar.gz | tar xvf -

  • On trouve aussi l’extension .tgz au lieu de .tar.gz

  • On trouve aussi l’extension .txz au lieu de .tar.xz

  • Il est possible, même sur une archive compressée, d’en extraire une partie : $ tar -Jxvf nomArchive.txz chemin/fichier

4. Autres utilitaires de création / extraction d’archives compressées

4.1. zip et unzip

$ zip -r nomArchive * (1)
$ unzip nomArchive.zip (2)
1 option -r archive aussi les sous répertoires (récursif). Crée une archive nomArchive.zip, à partir du répertoire courant.
2 extraction d’une archivve nomArchive.zip dans le répertoire courant.

4.2. 7z avec p7zip

$ p7zip -d nomArchive.7z (1)
1 option -d pour extraction

4.3. unrar-free et unrar

Il existe les commandes unrar-free et unrar dans les distributions GNU+Linux basées sur Debian pour l’extraction des archives au format propriétaire .rar.

5. Recompression de fichiers à format spécifiques (PNG, JPEG, FLAC, JS)

5.1. PNG / JPEG

Les commandes jpegoptim et zopflipng permettent de recompresser des images JPEG / PNG sans perte de qualité :

$ find . -name \*.jpeg -exec jpegoptim -pt (1)

$ find . -regextype posix-extended -iregex '.*(jpeg|jpg)' -print0 | xargs -0 -n 1 -P $((`nproc` / 2)) jpegoptim -pt (2)

$ find . -name \*.png -print0 | xargs -0 -n 1 -P $((`nproc` / 2)) -I {} zopflipng -m --lossy_8bit --lossy_transparent -y {} {} (3)
1 JPG monotask
2 JPE?G multitask ; See Find text in selected files for --print0 / -0 options.
3 PNG multitask

5.2. FLAC

La commande reflac permet de recompresser des musiques FLAC au niveau maximum en gardant les métadonnées originales au format ID3 :

$ reflac --best $album_folder/ (1)
1 reflac from chungy/reflac Github repository.

La command sox permet elle de ré-échantillonner un fichier audio pour se débarrasser du superflux à l’écoute (au dela du 16 bits 44100 Hz). Cas pratique pour un album entier (la commande sox est en fin de 2e ligne…) :

$ cd the_album/
$ find . -name "*.flac" -print0 | xargs -0 -n 1 -P 4 -I {} sox -S {} -r 48000 -b 16 "{}.sox.flac"
$ rename -f 's/\.sox\.flac//' *.flac

5.3. JavaScript

La commande uglifyjs permet de compresser et décompresser un fichier JavaScript. Le principe est simple, tous les caractères de mise en forme qui ne sont pas utils à l’interprêteur de JavaScript sont retirés (espaces, tabulations, retours à la ligne, commentaires).

$ uglifyjs file.js > file.min.js

Il est encore possible de changer les noms de variable et de fonction pour des noms plus courts. Mais ce traitement, effectué par un mangler comme yui-compressor, est par contre irréversible.

La commande js-beautify (du paquet jbeautifier sur les systèmes basés sur Debian), permet de ré-introduire automatiquement des caractères rendant le code lisible pour les humains (mais les commentaires retirés sont perdus).

$ js-beautify file.min.js > file.js