![如何重新压缩 200 万个 gzip 文件而不存储两次?](https://linux22.com/image/59034/%E5%A6%82%E4%BD%95%E9%87%8D%E6%96%B0%E5%8E%8B%E7%BC%A9%20200%20%E4%B8%87%E4%B8%AA%20gzip%20%E6%96%87%E4%BB%B6%E8%80%8C%E4%B8%8D%E5%AD%98%E5%82%A8%E4%B8%A4%E6%AC%A1%EF%BC%9F.png)
我有大约 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
传递到then 并删除。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