200万のgzipファイルを2回保存せずに再圧縮するにはどうすればよいですか?


8

約200万(60GiB)のgzip圧縮された小さなファイルがあり、それらすべてを非圧縮バージョンで含む圧縮アーカイブを作成したいと考えています。残念ながら、ディスクの空き容量は約70GiBしかないので、すべてを解凍して圧縮アーカイブを作成することはできません。言い換えれtar --file-filter="zcat" zcf file.tar.gz directoryば、コマンドラインスイッチのようなもの--file-filterがGNU tarに存在しない場合、どうすれば同等のことができますか?


マルチプロセッサマシンはありますか?
Anthon、2014年

1
@Anthon:このマシンではありませんが、将来の読者にとっては、そうだと思います。
d33tah 2014年

再圧縮する必要があるので、そこに何か利益があります。使用する特定の理由gzip?結合して圧縮するとスペースが節約されますが、xz-ed tarファイルに圧縮すると、さらに多くのメリットが得られます。それはオプションですか?
Anthon、2014年

どの圧縮プログラムでも実行できます。解凍されたが保存されていないファイルのtarファイルを作成できれば、他のプログラムにパイプすることができます。
d33tah 2014年

回答:


6

オプションを使用することもできますavfs(ここでは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

厄介なファイル名に関しては、これは壊れやすいことに注意してください。

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"

ファイルはで一時的に解凍され、アーカイブに追加されるとすぐに$tmpdir渡されcpio、削除されます。


1
また、マルチスレッドを使用pigzしている場合は、gzipの代わりに使用することをお勧めします:)
Christopher Stanley

2

これが私がこれまでに試みたものです-それはうまくいくようですが、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()

使用法: find . | script.py | gzip > file.tar.gz


ほぼ満杯のディスクで圧縮解除、特に再圧縮を行うと、何があっても処理が遅くなります。
クリスティアンCiupitu 2014年

@CristianCiupitu:私はなし|gzipで測定しましたが、圧縮されていないファイルは基本的にHDDに触れていなかったので、私はそれが遅くなるべきではありません。
d33tah 2014年

1
Deおよび再圧縮は、CPythonの最適化されたCコードで行われます。ディスクに触れないようにするバッファリングが含まれている可能性があります。
Anthon、2014年

1
見つける -exec cat \ {\} \; > / dev / nullは、この操作にかかる可能性のある時間の下限を提供する必要があります。あなたの問題の一部は、圧縮された形式と圧縮されていない形式の両方でファイルを含む大きなpythonオブジェクトの束を作成し、その後、ガベージコレクターが自分でクリーンアップすることだと思います。こちらをご覧ください:stackoverflow.com/questions/6115066/...
BitShifter

おそらく、非圧縮サイズ計算して、tarオブジェクトのようなgzipファイルに渡すことで、メモリを節約できます。
クリスティアンCiupitu 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.