Convertir archivos gzip a bzip2 de manera eficiente


10

Tengo un montón de archivos gzip que tengo que convertir a bzip2 de vez en cuando. Actualmente, estoy usando un script de shell que simplemente 'gunzip es cada archivo y luego' bzip2 es. Aunque esto funciona, lleva mucho tiempo completarlo.

¿Es posible hacer este proceso más eficiente? Estoy listo para sumergirme y mirar los códigos fuente de gunzip y bzip2 si es necesario, pero solo quiero estar seguro de la recompensa. ¿Hay alguna esperanza de mejorar la eficiencia del proceso?

Respuestas:


1

Esta pregunta se hizo hace mucho tiempo cuando pbzip2 no estaba disponible o no era capaz de comprimir desde stdin, pero ahora puede paralelizar los pasos de descompresión y compresión usando paralelo y pbzip2 (en lugar de bzip2 ):

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

que es significativamente más rápido que usar bzip2 .


Hola, he cambiado la respuesta aceptada a esta, ya que esta es la mejor opción para las personas que hoy se encuentran con la pregunta. Gracias por la pbzip2mención En caso de que el enlace no se cargue para nadie más, aquí está la página del proyecto y la página del manual .
sundar - Restablece a Monica

15

En lugar de gunzip en un paso y bzip2 en otro, me pregunto si tal vez sería más eficiente usar tuberías. Algo comogunzip --to-stdout foo.gz | bzip2 > foo.bz2

Estoy pensando con dos o más CPU, esto definitivamente sería más rápido. Pero tal vez incluso con un solo núcleo. Sin embargo, admito vergonzosamente no haber probado esto.


2
+1 para tuberías, la E / S de disco es algo que desea evitar. En cuanto a la compresión, a menos que me equivoque, bzip2 no es paralelo. Tendrías que usar algo como pbzip2 para comprimir en paralelo: compress.ca/pbzip2
gustafc

... y desafortunadamente, no parece haber ninguna utilidad de descompresión gzip paralela disponible.
gustafc

@gustafc: Gracias por el enlace a pbzip2, fue muy útil ... @OP: me alejé de las tuberías bcos Quiero poder lidiar con archivos gz corruptos, etc., sin perderlos en la tubería ...
Sundar - Restablecer Monica

44
@gustafc: Incluso si bzip2y gzipno funcionan en paralelo internamente, al usar una tubería puede hacer que funcionen en paralelo, porque una tubería inicia implícitamente dos procesos, que se ejecutarán en paralelo. Entonces, al menos la descompresión y la compresión se ejecutarán en paralelo.
sleske

1
@sleske, a pesar de que tiene razón en teoría, bzip2el uso de la CPU eclipsa a gunzipuno, por lo que en la práctica el paralelismo que se obtiene aquí es mínimo. Sin embargo, ¡no tener que hacer el disco IO sigue siendo agradable!
Johan Walles

6

El paralelo GNU ( http://www.gnu.org/software/parallel ) podría ser una opción si tiene múltiples núcleos (o incluso múltiples máquinas):

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

Lea el tutorial / página de manual para obtener detalles y opciones.


3

Lo que estás haciendo actualmente es tu mejor apuesta. No hay una herramienta de conversión disponible, e intentar bzip2 un archivo ya comprimido no es realmente una opción, ya que con frecuencia tiene efectos no deseados. Como el algoritmo es diferente, la conversión implicaría recuperar los datos originales independientemente. A menos que, por supuesto, gzipping haya sido un paso en el proceso de bzip2, en el que lamentablemente no lo es.


No los algoritmos tienen ningún pasos se superponen de tal manera que yo pudiera saltar un paso de descompresión gzip y lo mismo en bzip compresión también?
sundar - Restablece a Mónica

2
@sundar No lo creo. gzipusa Leimpel-Ziv 77, mientras bzip2usa Burrows-Wheeler. Diferentes algoritmos, me temo.
nuevo123456

2

Ocasionalmente, necesito hacer lo mismo con los archivos de registro. Comienzo con los archivos * .gz más pequeños primero ( ls -rS), gunzip y luego y bzip2 individualmente. No sé si es posible dirigir la salida gunzip directamente a la entrada bzip2. El comando bzip2 es mucho más lento en la compresión que gunzip en la descompresión que puede consumir la memoria e intercambiar espacio en el host.

Mejoras o sugerencias son bienvenidas. Aquí está mi único revestimiento:

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

Gracias por el aporte, el punto sobre la diferencia en velocidad entre los dos procesos y su implicación es importante.
sundar - Restablecer Monica


1

Solo tuve que hacer esto hace unos minutos:

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

Donde rezipse definiría como:

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

Opcionalmente, también puede hacerlo multiproceso utilizando una -Popción con xargs, pero tenga cuidado con esa. (¡Comienza bajo!)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.