Bagaimana cara mengkompres ulang 2 juta file gzip tanpa menyimpannya dua kali?

8

Saya memiliki sekitar 2 juta (60GiB) file kecil yang di-gzip dan saya ingin membuat arsip terkompresi yang berisi semuanya dalam versi yang tidak terkompresi. Sayangnya, saya tidak bisa hanya mengompres semuanya dan kemudian membuat arsip terkompresi karena saya hanya memiliki sekitar 70GiB ruang disk kosong. Dengan kata lain, bagaimana saya bisa melakukan yang setara tar --file-filter="zcat" zcf file.tar.gz directoryjika saklar baris perintah seperti --file-filtertidak ada di tar GNU?

d33tah
sumber
Apakah Anda memiliki mesin multiprosesor?
Anthon
1
@Anthon: bukan pada mesin ini, tetapi untuk pembaca masa depan kita mungkin berasumsi ya.
d33tah
Karena Anda harus mengkompres ulang, ada keuntungan di sana. Ada alasan khusus mengapa harus menggunakan gzip? Menggabungkan dan mengompresi menghemat ruang, tetapi Anda akan mendapatkan lebih banyak jika Anda mengompres ke xzfile tar -ed. Apakah itu pilihan?
Anthon
Program kompresi apa pun bisa dilakukan. Jika saya dapat membuat file tar dari file yang tidak di-dekompresi tetapi tidak disimpan, saya dapat mengirimkannya ke program lain.
d33tah

Jawaban:

6

Sebuah opsi dapat digunakan avfs(di sini dengan asumsi sistem 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
Stéphane Chazelas
sumber
3

Perhatikan, bahwa ini rapuh ketika menyangkut nama file yang tidak menyenangkan.

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"

File-file tersebut tidak terkompresi sementara di bawah $tmpdir, diteruskan ke cpiobegitu segera setelah mereka ditambahkan ke arsip, dihapus.

Cristian Ciupitu
sumber
1
Juga, jika Anda memiliki multi-utas, saya akan menyarankan menggunakan pigzsebagai alternatif untuk gzip :)
Christopher Stanley
2

Inilah yang saya coba sejauh ini - sepertinya berhasil, tetapi sangat lambat, bahkan dengan 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()

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

d33tah
sumber
Tanpa kompresi dan terutama kompresi pada disk yang hampir penuh, akan menjadi lambat, apa pun yang terjadi.
Cristian Ciupitu
@CristianCiupitu: Saya mengukur tanpa |gzipdan file yang tidak terkompresi pada dasarnya tidak menyentuh HDD, jadi IMHO seharusnya tidak terlalu lambat.
d33tah
1
De dan Recompressing dilakukan dalam kode C yang dioptimalkan dalam CPython. Mungkin ada buffering yang terlibat yang menyebabkan disk tidak disentuh.
Anthon
1
Temukan . -exec cat \ {\} \; > / dev / null harus memberikan batasan yang lebih rendah pada jumlah waktu yang bisa diambil oleh operasi ini. Saya akan membayangkan bahwa bagian dari masalah Anda adalah pembuatan banyak objek python besar yang berisi file Anda dalam bentuk terkompresi dan tidak terkompresi dan kemudian membiarkan pengumpul sampah membersihkan diri Anda sendiri. lihat di sini: stackoverflow.com/questions/6115066/…
BitShifter
Anda mungkin dapat menghemat sebagian memori dengan mencari tahu ukuran yang tidak terkompresi dan meneruskannya ke tarfile seperti objek gzip.
Cristian Ciupitu