Conversion efficace de fichiers gzip en bzip2


10

J'ai un tas de fichiers gzip que je dois convertir en bzip2 de temps en temps. Actuellement, j'utilise un script shell qui se contente de "gunzip" chaque fichier, puis "bzip2". Bien que cela fonctionne, cela prend beaucoup de temps.

Est-il possible de rendre ce processus plus efficace? Je suis prêt à plonger et à regarder les codes sources de gunzip et bzip2 si nécessaire, mais je veux juste être sûr du résultat. Y a-t-il un espoir d'améliorer l'efficacité du processus?

Réponses:


1

Cette question a été posée il y a longtemps lorsque pbzip2 n'était pas disponible ou n'était pas capable de compresser à partir de stdin, mais vous pouvez désormais paralléliser les étapes de décompression et de compression à l'aide de parallel et pbzip2 (au lieu de bzip2 ):

ls *.gz | parallel "gunzip -c {} | pbzip2 -c > {.}.bz2"

ce qui est nettement plus rapide que d'utiliser bzip2 .


Salut, j'ai changé la réponse acceptée à celle-ci car cela donne la meilleure option pour les gens tombant sur la question aujourd'hui. Merci pour la pbzip2mention. Si le lien ne se charge pas pour quelqu'un d'autre, voici la page du projet et la page de manuel .
sundar

15

Plutôt que gunzip dans une étape et bzip2 dans une autre, je me demande s'il serait peut-être plus efficace d'utiliser des tuyaux. Quelque chose commegunzip --to-stdout foo.gz | bzip2 > foo.bz2

Je pense qu'avec deux processeurs ou plus, ce serait certainement plus rapide. Mais peut-être même avec un seul cœur. Je reconnais honteusement de ne pas avoir essayé cela, cependant.


2
+1 pour la tuyauterie, les E / S disque sont quelque chose que vous voulez éviter. En ce qui concerne la compression, sauf erreur de ma part, bzip2 n'est pas parallèle. Il faudrait utiliser quelque chose comme pbzip2 pour compresser en parallèle: compression.ca/pbzip2
gustafc

... et malheureusement, il ne semble pas y avoir d'utilitaire de décompression gzip parallèle disponible.
gustafc

@gustafc: Merci pour le lien vers pbzip2, qui a été très utile ... @OP: Je me suis détourné des tuyauteries bcos, je veux pouvoir gérer les fichiers gz corrompus, etc., sans les perdre dans le tuyau ...
sundar

4
@gustafc: Même si bzip2et gzipne fonctionnent pas en interne en parallèle, à l'aide d' un tuyau , vous pouvez faire travailler en parallèle, car une conduite commence implicitement deux processus qui vont fonctionner en parallèle. Ainsi, au moins la décompression et la compression s'exécuteront en parallèle.
sleske

1
@sleske, bien que vous ayez raison en théorie, bzip2l'utilisation du CPU éclipse gunzipcelle, donc en pratique le parallélisme que vous obtenez ici est minime. Ne pas avoir à faire d'E / S sur disque est quand même bien!
Johan Walles

6

GNU parallèle ( http://www.gnu.org/software/parallel ) peut être une option si vous avez plusieurs cœurs (ou même plusieurs machines):

ls *.gz | parallel "gunzip -c {} | bzip2 > {.}.bz2"

Lisez le tutoriel / page de manuel pour les détails et les options.


3

Ce que vous faites actuellement est votre meilleur pari. Il n'y a pas d'outil de conversion disponible, et tenter de bzip2 un fichier déjà compressé n'est pas vraiment une option, car il a souvent des effets indésirables. Étant donné que l'algorithme est différent, la conversion impliquerait de récupérer les données d'origine malgré tout. À moins bien sûr que le gzipping ne soit une étape du processus bzip2, ce qui n'est malheureusement pas le cas.


Les algorithmes n'ont-ils pas d' étapes qui se chevauchent de telle sorte que je puisse sauter une étape dans la décompression gzip et la même chose dans la compression bzip également?
sundar

2
@sundar je ne pense pas. gziputilise Leimpel-Ziv 77, tandis que bzip2Burrows-Wheeler. Différents algorithmes, je le crains.
new123456

2

Parfois, je dois faire la même chose avec les fichiers journaux. Je commence par les plus petits fichiers * .gz d'abord ( ls -rS), gunzip, puis et bzip2 individuellement. Je ne sais pas s'il est possible de diriger la sortie gunzip directement vers l'entrée bzip2. La commande bzip2 est tellement plus lente en compression que gunzip en décompression qu'elle peut consommer de la mémoire et échanger de l'espace sur l'hôte.

Les améliorations ou suggestions sont les bienvenues. Voici ma seule doublure:

for i in $(ls -rS *.gz | sed 's/\.gz//'); do gunzip ${i}.gz; bzip2 -9 ${i}; done

Merci pour la contribution, le point sur la différence de vitesse entre les deux processus et son implication est important.
sundar


1

Je viens de le faire il y a quelques minutes:

find . -name "*.gz" | perl -pi -e 's/\.gz$//g;' | xargs -n1 ./rezip

rezipserait défini comme:

#!/bin/bash
gunzip -v $1.gz && bzip2 -9v $1

En option, vous pouvez également le rendre multi-thread en utilisant une -Poption avec xargs, mais soyez prudent avec celle-ci. (Commencez bas!)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.