Convertendo arquivos gzip para bzip2 eficientemente


10

Eu tenho um monte de arquivos gzip que tenho que converter para bzip2 de vez em quando. Atualmente, estou usando um script de shell que simplesmente 'gunzip' é cada arquivo e depois 'bzip2' é. Embora isso funcione, leva muito tempo para ser concluído.

É possível tornar esse processo mais eficiente? Estou pronto para mergulhar e analisar os códigos-fonte do gunzip e do bzip2, se necessário, mas só quero ter certeza do pagamento. Existe alguma esperança de melhorar a eficiência do processo?

Respostas:


1

Esta pergunta foi feita há muito tempo quando o pbzip2 não estava disponível ou não era capaz de compactar a partir do stdin, mas agora você pode paralelizar as etapas de descompactação e compactação usando o parallel e o pbzip2 (em vez do bzip2 ):

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

o que é significativamente mais rápido do que usar o bzip2 .


Olá, eu mudei a resposta aceita para essa, pois isso oferece a melhor opção para as pessoas que se deparam com a pergunta hoje. Obrigado pela pbzip2menção. Caso o link não seja carregado para mais ninguém, aqui está a página do projeto e a página do manual .
sundar - Restabelece Monica

15

Em vez de fazer o gunzip em uma etapa e o bzip2 em outra, pergunto-me se talvez fosse mais eficiente usar tubos. Algo comogunzip --to-stdout foo.gz | bzip2 > foo.bz2

Estou pensando com duas ou mais CPUs, isso definitivamente seria mais rápido. Mas talvez até com apenas um núcleo. Eu vergonhosamente admito que não tentei isso, no entanto.


2
+1 para canalização, a E / S do disco é algo que você deseja evitar. Quanto à compactação, a menos que eu esteja enganado, o bzip2 não é paralelo. Você teria que usar algo como pbzip2 a compressa em paralelo: compression.ca/pbzip2
gustafc

... e, infelizmente, não parece haver nenhum utilitário de descompressão paralelo gzip disponível.
gustafc

@gustafc: Obrigado pelo link para pbzip2, que foi muito útil ... @OP: Evitei o piping bcos. Quero poder lidar com arquivos gz corrompidos etc., sem perdê-los no pipe ...
Sundar - Restabelece Monica 18/08/09

4
@gustafc: Mesmo se bzip2e gzipnão funcionam em paralelo internamente, por meio de um tubo que você pode tê-los trabalho em paralelo, porque um tubo começa implicitamente dois processos, que vai correr em paralelo. Portanto, pelo menos descompactação e compactação serão executadas em paralelo.
fácil

1
@sleske, mesmo que você esteja certo na teoria, bzip2o uso da CPU gunzipé menor do que o anterior ; portanto, na prática, o paralelismo que você obtém aqui é mínimo. Não ter que fazer E / S de disco ainda é bom!
Johan Walles

6

O paralelo GNU ( http://www.gnu.org/software/parallel ) pode ser uma opção se você tiver vários núcleos (ou até várias máquinas):

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

Leia a página tutorial / man para obter detalhes e opções.


3

O que você está fazendo atualmente é sua melhor aposta. Não existe uma ferramenta de conversão disponível, e tentar compactar com bzip2 um arquivo já compactado não é realmente uma opção, pois geralmente produz efeitos indesejados. Como o algoritmo é diferente, a conversão envolveria a recuperação dos dados originais, independentemente. A menos, é claro, que o gzipping tenha sido um passo no processo do bzip2, no qual infelizmente não é.


Não os algoritmos têm quaisquer passos que se sobrepõem de tal forma que eu pudesse pular um passo na descompressão gzip e o mesmo em bzip compressão também?
Sundar - Restabelece Monica 19/08/09

2
@ Sundar Eu não pensaria assim. gzipusa Leimpel-Ziv 77, enquanto bzip2usa Burrows-Wheeler. Algoritmos diferentes, receio.
new123456

2

Ocasionalmente, preciso fazer o mesmo com arquivos de log. Começo com os menores arquivos * .gz primeiro ( ls -rS), gunzip e depois os bzip2 individualmente. Não sei se é possível direcionar a saída do gunzip diretamente para a entrada bzip2. O comando bzip2 é muito mais lento na compactação do que o gunzip está na descompressão que pode consumir a memória e trocar espaço no host.

Melhorias ou sugestões são bem-vindas. Aqui está o meu forro:

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

Obrigado pela contribuição, o ponto sobre a diferença de velocidade entre os dois processos e suas implicações é importante.
sundar - Restabelece Monica


1

Só tive que fazer isso alguns minutos atrás:

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

Onde rezipseria definido como:

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

Opcionalmente, você também pode torná-lo multiencadeado usando uma -Popção com xargs, mas tenha cuidado com ela. (Comece baixo!)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.