Comment dois-je combiner plusieurs fichiers compressés en une seule archive?

10

J'ai quelques centaines de .tar.xzfichiers qui sont presque identiques (ce sont des vidages de base de données quotidiens et la base de données change lentement).

Je pense qu'en raison des similitudes des fichiers non compressés, ils se compresseront très bien et des tests à petite échelle ont montré que la compression d'un nombre quelconque de ces fichiers non compressés crée une archive à peine plus grande que l'un d'eux.

Mon problème est que tous les fichiers non compressés feraient quelques téraoctets (le taux de compression est d'environ 25: 1), et je n'ai pas beaucoup d'espace disque à utiliser comme zone de travail.

Existe-t-il un moyen de traiter les fichiers compressés individuellement un par un, en les ajoutant à une seule archive et en conservant les avantages de les compresser ensemble?

jl6
la source
Avez-vous essayé de l'écrire pour décompresser un fichier, ajouter tous les fichiers à une archive donnée, puis passer au suivant?
darnir

Réponses:

10

Étant donné que les fichiers tar sont un format de streaming - vous pouvez les catdeux ensemble et obtenir un résultat presque correct - vous n'avez pas du tout besoin de les extraire sur le disque pour ce faire. Vous pouvez décompresser (uniquement) les fichiers, les concaténer ensemble et recompresser ce flux:

xzcat *.tar.xz | xz -c > combined.tar.xz

combined.tar.xzsera un tarball compressé de tous les fichiers dans les tarballs des composants qui n'est que légèrement corrompu. Pour extraire, vous devrez utiliser l' --ignore-zerosoption (dans GNU tar), car les archives ont un marqueur "fin de fichier" qui apparaîtra au milieu du résultat. En dehors de cela, cependant, tout fonctionnera correctement.

GNU tarprend également en charge un --concatenatemode de production d'archives combinées. Cela a les mêmes limitations que ci-dessus - vous devez utiliser --ignore-zerospour extraire - mais cela ne fonctionne pas avec les archives compressées. Vous pouvez construire quelque chose pour le faire fonctionner en utilisant la substitution de processus, mais c'est un problème et encore plus fragile.

S'il y a des fichiers qui apparaissent plus d'une fois dans différents fichiers tar, cela ne fonctionnera pas correctement, mais vous avez malgré tout ce problème. Sinon, cela vous donnera ce que vous voulez - canaliser la sortie xzest de toute façon comment tarcomprime sa sortie.


Si les archives qui ne fonctionnent qu'avec une tarimplémentation particulière ne conviennent pas à vos besoins, l'ajout à l'archive avec rest votre ami:

tar cJf combined.tar.xz dummy-file
for x in db-*.tar.xz
do
    mkdir tmp
    pushd tmp
    tar xJf "../$x"
    tar rJf ../combined.tar.xz .
    popd
    rm -r tmp
done

Cela extrait seulement une seule archive à la fois, donc l'espace de travail est limité à la taille du contenu d'une seule archive. La compression est diffusée comme elle l'aurait été si vous aviez créé l'archive finale en même temps, elle sera donc aussi bonne qu'elle aurait pu l'être. Vous faites beaucoup de décompression et de recompression excessives qui rendront cela plus lent que les catversions, mais l'archive résultante fonctionnera n'importe où sans aucun support spécial.

Notez que - selon ce que vous voulez exactement - l'ajout des fichiers tar non compressés eux-mêmes à une archive peut suffire. Ils compresseront (presque) exactement ainsi que leur contenu dans un seul fichier, et cela réduira la surcharge de compression pour chaque fichier. Cela ressemblerait à quelque chose comme:

tar cJf combined.tar.xz dummy-file
for x in db-*.tar.xz
do
    xz -dk "$x"
    tar rJf combined.tar.xz "${x%.xz}"
    rm -f "${x%.xz}"
done

Ceci est légèrement moins efficace en termes de taille compressée finale car il y a des en-têtes tar supplémentaires dans le flux, mais permet d'économiser du temps sur l'extraction et l'ajout de tous les fichiers en tant que fichiers. Vous finiriez par combined.tar.xzcontenir de nombreux db-*.tarfichiers (non compressés) .

Michael Homer
la source
Merci, votre deuxième option semble convenir à mon objectif, mais pourriez-vous développer votre dernier paragraphe? À quoi cela ressemblerait-il?
jl6
@ jl6: Voir modifier.
Michael Homer
Désolé, je viens juste de tester cela. Votre deuxième méthode me donne cette erreur:tar: Cannot update compressed archives
jl6