Concatenação rápida de vários arquivos GZip

93

Eu tenho uma lista de arquivos gzip:

file1.gz
file2.gz
file3.gz

Existe uma maneira de concatenar ou gzipar esses arquivos em um arquivo gzip sem ter que descompactá- los?

Na prática, usaremos isso em um banco de dados da web (CGI). Onde a web receberá uma consulta do usuário e listará todos os arquivos com base na consulta e os apresentará em um arquivo em lote de volta para o usuário.

neversaint
fonte

Respostas:

107

Com arquivos gzip, você pode simplesmente concatenar os arquivos juntos, assim:

cat file1.gz file2.gz file3.gz > allfiles.gz

De acordo com o RFC gzip ,

Um arquivo gzip consiste em uma série de "membros" (conjuntos de dados compactados). [...] Os membros simplesmente aparecem um após o outro no arquivo, sem nenhuma informação adicional antes, entre ou depois deles.

Observe que isso não é exatamente o mesmo que construir um único arquivo gzip dos dados concatenados; entre outras coisas, todos os nomes de arquivos originais são preservados. No entanto, gunzip parece tratá-lo como equivalente a uma concatenação.

Como as ferramentas existentes geralmente ignoram os cabeçalhos de nome de arquivo para os membros adicionais, não é fácil extrair arquivos individuais do resultado. Se você quiser que isso seja possível, crie um arquivo ZIP. ZIP e GZIP usam o algoritmo DEFLATE para a compressão propriamente dita (ZIP suporta alguns outros algoritmos de compressão assim como uma opção - o método 8 é o que corresponde à compressão de GZIP); a diferença está no formato dos metadados. Como os metadados são descompactados, é simples remover os cabeçalhos gzip e adicionar cabeçalhos de arquivo ZIP e um registro de diretório central. Consulte a especificação do formato gzip e a especificação do formato ZIP .

bdonlan
fonte
41
Não. Apenas cat file1.gz file2.gz file3.gz > allfiles.gz. É realmente simples assim :)
bdonlan
1
tecnicamente falando, eles são preservados. Acontece que as ferramentas existentes geralmente não têm a capacidade de extraí-las separadamente. Você pode querer construir um cabeçalho e diretório ZIP - o formato ZIP usa o mesmo algoritmo de compressão subjacente, então é apenas uma questão de alterar os metadados (descompactados). Dê uma olhada em gzip.org/zlib/rfc-gzip.html (o formato de origem) e pkware.com/documents/casestudies/APPNOTE.TXT .
bdonlan
20
Melhor do que construir um zip de arquivos gz, basta compactá-los. É o mesmo que a catresposta, mas com alguns metadados extras. Você pode descompactá-los posteriormente para obter os nomes dos arquivos originais e, em seguida, descompactar todos ou apenas alguns, conforme necessário.
sorpigal
2
@alvas, zcatdescompacta sua entrada, para que você obtenha uma saída descompactada com uma .gzextensão.
bdonlan
2
Aparentemente, existem algumas ferramentas que irão parar por engano quando chegarem ao final do primeiro membro gzipado. github.com/pysam-developers/pysam/issues/…
Jeremy Leipzig
51

Aqui está o que man 1 gzipdiz sobre sua necessidade.

Vários arquivos compactados podem ser concatenados. Nesse caso, o gunzip extrairá todos os membros de uma vez. Por exemplo:

gzip -c file1  > foo.gz
gzip -c file2 >> foo.gz

Então

gunzip -c foo

é equivalente a

cat file1 file2

Não é preciso dizer que file1pode ser substituído por file1.gz.

Você deve observar isto:

gunzip irá extrair todos os membros de uma vez

Portanto, para obter todos os membros individualmente, você terá que usar algo adicional ou escrever, se desejar.

No entanto, isso também é abordado na página de manual.

Se você deseja criar um único arquivo com vários membros para que os membros possam ser extraídos independentemente, use um arquivador como tar ou zip. GNU tar suporta a -zopção de invocar gzip de forma transparente. O gzip foi desenvolvido como um complemento do tar, não como um substituto.

Nehal Dattani
fonte
13

Basta usar cat. É muito rápido (0,2 segundos para 500 MB para mim)

cat *gz > final
mv final final.gz

Você pode então ler a saída com zcat para ter certeza de que é bonita:

zcat final.gz

Eu tentei a outra resposta de 'gz -c' mas acabei com lixo ao usar arquivos já compactados com gzip como entrada (acho que os compactou duas vezes).

PV:

Melhor ainda, se você tiver, 'pv' em vez de gato:

pv *gz > final
mv final final.gz

Isso fornece uma barra de progresso conforme funciona, mas faz a mesma coisa que o gato.

Matiu
fonte
11

Você pode criar um arquivo tar desses arquivos e então gzip o arquivo tar para criar o novo arquivo gzip

tar -cvf newcombined.tar file1.gz file2.gz file3.gz
gzip newcombined.tar
Drona
fonte
8
Por que exatamente você deve compactar o novo arquivo tar? Já está compactado (exceto os metadados do tar, que devem ser pequenos).
thiton
2
Você está certo. Não haveria muita diferença no tamanho do arquivo se você o gzipou ou não porque os arquivos individuais já estão compactados. É só porque ele queria ter o arquivo gzip dos três arquivos individuais.
Drona
1
O gzip extra apenas retarda o acesso ao conteúdo sem ganho. Parece-me que o requisito de OPs é realmente que o arquivo resultante seja um único arquivo, e não há razão para supor que o arquivo resultante deva ser um arquivo gzip.
mc0e