2백만 개의 gzip 파일을 두 번 저장하지 않고 다시 압축하는 방법은 무엇입니까?

2백만 개의 gzip 파일을 두 번 저장하지 않고 다시 압축하는 방법은 무엇입니까?

약 200만 개(60GiB)의 작은 gzip 파일이 있고 모든 파일의 압축되지 않은 버전이 포함된 압축 아카이브를 만들고 싶습니다. 안타깝게도 여유 디스크 공간이 약 70GiB밖에 없기 때문에 압축을 모두 풀고 압축된 아카이브를 생성할 수 없습니다. 즉, GNU tar 에 tar --file-filter="zcat" zcf file.tar.gz directory그러한 명령줄 스위치가 없다면 어떻게 동등한 작업을 수행할 수 있습니까?--file-filter

답변1

한 가지 옵션은 다음과 같습니다.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

답변2

불쾌한 파일 이름의 경우 이는 취약하다는 점에 유의하세요.

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

답변3

지금까지 시도한 내용은 다음과 같습니다. 작동하는 것처럼 보이지만 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

관련 정보