Como devo combinar muitos arquivos compactados em um único arquivo?

10

Eu tenho algumas centenas de .tar.xzarquivos que são quase idênticos (são despejos diários do banco de dados e o banco de dados muda lentamente).

Acredito que, devido às semelhanças nos arquivos descompactados, eles serão compactados muito bem, e testes em pequena escala mostraram que a compactação de qualquer número desses arquivos descomprimidos cria um arquivo apenas um pouco maior que um deles.

Meu problema é que todos os arquivos descompactados teriam alguns terabytes (a taxa de compactação é de cerca de 25: 1) e não tenho muito espaço em disco para usar como área de trabalho.

Existe uma maneira de processar os arquivos compactados individuais, um de cada vez, adicionando-os a um único arquivo e mantendo os benefícios de compactá-los juntos?

jl6
fonte
Você tentou criar um script para descompactar um arquivo, adicionar todos os arquivos a um determinado arquivo morto e depois passar para o próximo?
darnir

Respostas:

10

Como os arquivos tar são um formato de streaming - você pode catdois deles juntos e obter um resultado quase correto -, não é necessário extraí-los para o disco para fazer isso. Você pode descompactar (apenas) os arquivos, concatená-los e recomprimir esse fluxo:

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

combined.tar.xzserá um tarball compactado de todos os arquivos nos tarballs do componente que está apenas ligeiramente corrompido. Para extrair, você terá que usar a --ignore-zerosopção (no GNU tar), porque os arquivos possuem um marcador "fim de arquivo" que aparecerá no meio do resultado. Fora isso, porém, tudo funcionará corretamente.

O GNU tartambém suporta um --concatenatemodo para produzir arquivos combinados. Isso tem as mesmas limitações acima - você deve usar --ignore-zerospara extrair - mas não funciona com arquivos compactados. Você pode criar algo para enganá-lo no trabalho usando substituição de processo, mas é um aborrecimento e ainda mais frágil.

Se houver arquivos que aparecem mais de uma vez em arquivos tar diferentes, isso não funcionará corretamente, mas você terá esse problema independentemente. Caso contrário, isso lhe dará o que você deseja - canalizando a saída xzé como tarcomprime sua saída de qualquer maneira.


Se os arquivos que funcionam apenas com uma tarimplementação específica não são adequados para seus propósitos, anexar ao arquivo ré seu amigo:

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

Isso apenas extrai um único arquivo de cada vez, portanto, o espaço de trabalho é limitado ao tamanho do conteúdo de um único arquivo. A compactação está sendo transmitida exatamente como teria sido se você tivesse feito o arquivo final de uma só vez, para que fique o melhor que poderia ter sido. Você faz muita descompressão e recompressão em excesso que tornarão isso mais lento que as catversões, mas o arquivo resultante funcionará em qualquer lugar sem nenhum suporte especial.

Observe que, dependendo do que você deseja, basta adicionar os arquivos tar não compactados a um arquivo morto. Eles compactarão (quase) exatamente o conteúdo em um único arquivo e reduzirá a sobrecarga da compactação para cada arquivo. Isso seria algo como:

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

Isso é um pouco menos eficiente em termos do tamanho final compactado, porque há cabeçalhos tar adicionais no fluxo, mas economiza algum tempo na extração e na adição de todos os arquivos como arquivos. Você acabaria combined.tar.xzcontendo muitos db-*.tararquivos (não compactados) .

Michael Homer
fonte
Obrigado, sua segunda opção parece adequada para o meu propósito, mas você poderia elaborar seu último parágrafo? Como isso seria?
Jl6
@ jl6: Veja a edição.
Michael Homer
Desculpe, apenas consegui testar isso. Seu segundo método me dá este erro: tar: Cannot update compressed archives
#