Como recomprimir 2 milhões de arquivos gzip sem armazená-los duas vezes?


8

Eu tenho cerca de 2 milhões (60GiB) de arquivos pequenos compactados em gzip e gostaria de criar um arquivo compactado contendo todos eles em uma versão descompactada. Infelizmente, não posso simplesmente descompactá-los todos e criar o arquivo compactado, pois tenho apenas 70GiB de espaço livre em disco. Em outras palavras, como posso fazer um equivalente tar --file-filter="zcat" zcf file.tar.gz directoryse a opção de linha de comando --file-filternão existe no tar GNU?


Você tem uma máquina multiprocessadora?
— Anthon

1
@ Anthon: não nesta máquina, mas para os futuros leitores, podemos assumir que sim.
— amigos estão dizendo sobre d33tah

Como você precisa recomprimir, há algo de ganho lá. Alguma razão específica para usar gzip? A combinação e a compactação economizam espaço, mas você ganharia muito mais se comprimir em um xzarquivo tar ed. Isso é uma opção?
— Anthon

Qualquer programa de compactação faria. Se eu posso criar um arquivo tar dos arquivos descompactados, mas não armazenados, posso canalizá-lo para qualquer outro programa.
— precisa

Respostas:


6

Uma opção poderia ser usar avfs(aqui assumindo um sistema GNU):

mkdir ~/AVFS &&
avfsd ~/AVFS &&
cd ~/AVFS/where/your/gz/files/are/ &&
find . -name '*.gz' -type f -printf '%p#\0' |
  tar --null -T - --transform='s/.gz#$//' -cf - | pigz > /dest/file.tar.gz

3

Observe que isso é frágil quando se trata de nomes de arquivos desagradáveis.

dir_with_small_files=/home/john/files
tmpdir=/tmp/ul/dst
tarfile=/tmp/ul.tar
mkfifo "${tarfile}"

gzip <"${tarfile}" >"${tarfile}.gz" &

find "$dir_with_small_files" -type f | \
while read src; do
    dstdir="${tmpdir}/$(dirname $src)"
    dst="$(basename $src .gz)"
    mkdir -p "$dstdir"
    gunzip <"$src" >"${dstdir}/${dst}"
    # rm "$src" # uncomment to remove the original files
    echo "${dstdir}/${dst}"
done | \
cpio --create --format=ustar -v --quiet 2>&1 >"${tarfile}" | \
while read x; do
    rm "$x"
done

# clean-up
rm "$tarfile"
rm -r "$tmpdir"

Os arquivos são descompactados temporariamente em $tmpdir, transferidos para cpioentão assim que são adicionados ao arquivo, removidos.


1
Além disso, se você tem múltiplas threads, sugiro usar pigzcomo uma alternativa para gzip :)
— Christopher Stanley

2

Aqui está o que eu tentei até agora - parece funcionar, mas é terrivelmente lento, mesmo com o PyPy:

#!/usr/bin/python

import tarfile
import os
import gzip
import sys
import cStringIO

tar = tarfile.open("/dev/stdout", "w|")
for name in sys.stdin:
    name = name[:-1]  # remove the trailing newline
    try:
        f = gzip.open(name)
        b = f.read()
        f.close()
    except IOError:
        f = open(name)
        b = f.read()
        f.close()
    # the [2:] there is to remove ./ from "find" output
    ti = tarfile.TarInfo(name[2:])
    ti.size = len(b)
    io = cStringIO.StringIO(b)
    tar.addfile(ti, io)
tar.close()

Uso: find . | script.py | gzip > file.tar.gz


A descompressão e, especialmente, a recompressão em um disco que está quase cheio, será lento, não importa o quê.
— Cristian Ciupitu

@CristianCiupitu: Eu medi sem |gzipe o arquivo não compactado não tocou basicamente no disco rígido, então IMHO não deve ser tão lento.
— precisa

1
De e Recompressing são feitas no código C otimizado no CPython. Pode haver buffer envolvido que faz com que o disco não seja tocado.
— Anthon

1
encontrar . -exec cat \ {\} \; > / dev / null deve fornecer um limite inferior para a quantidade de tempo que essa operação pode levar. Eu imagino que parte do seu problema é a criação de um monte de objetos python grandes que contêm seus arquivos em formas compactadas e descompactadas e, em seguida, deixar o coletor de lixo limpar você mesmo. veja aqui: stackoverflow.com/questions/6115066/…
— BitShifter

Você provavelmente poderia economizar memória, descobrindo o tamanho descompactado e passando para taro arquivo gzip como objeto.
— Cristian Ciupitu
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.