如何在不存储两次的情况下重新压缩200万个gzip文件?


8

我有大约200万(60GiB)压缩的小文件,我想创建一个压缩的存档,其中包含所有未压缩的版本。不幸的是,我不能全部解压缩它们,然后创建压缩的存档,因为我只有大约70GiB的可用磁盘空间。换句话说,我该如何等效于GNU tar中不存在tar --file-filter="zcat" zcf file.tar.gz directory类似的命令行开关--file-filter


您有多处理器计算机吗?
Anthon 2014年

1
@Anthon:不在这台机器上,但是对于未来的读者,我们可能会认为是的。
d33tah 2014年

当您必须重新压缩时,会有一些好处。为什么要使用任何特定原因gzip?组合和压缩可以节省空间,但是如果压缩为xz-ed tar文件,则会获得更多收益。那是一个选择吗?
Anthon 2014年

任何压缩程序都可以。如果可以创建已解压缩但未存储的文件的tar文件,则可以将其通过管道传输到任何其他程序。
d33tah 2014年

Answers:


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"

这些文件在临时解压缩$tmpdircpio一旦将它们添加到存档中,则传递到,然后将其删除。


1
另外,如果您有多线程,我建议您使用pigzgzip作为替代:)
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


无论什么情况,在几乎已满的磁盘上进行解压缩(尤其是重新压缩)都会很慢。
Cristian Ciupitu 2014年

@CristianCiupitu:我测得没有|gzip,未压缩的文件基本上没有接触硬盘,所以恕我直言,它应该不会太慢。
d33tah 2014年

1
解压缩和重新压缩是在CPython中以优化的C代码完成的。可能涉及缓冲,导致无法触摸光盘。
Anthon 2014年

1
找 。-exec cat \ {\} \; > / dev / null应该提供此操作可能花费的时间下限。我想您的问题的一部分是创建一堆包含压缩和未压缩形式文件的大型python对象,然后让您自己清理垃圾回收器。在这里看到:stackoverflow.com/questions/6115066/...
BitShifter

您可以通过计算未压缩的大小并传递给targzip文件(如object)来节省一些内存。
Cristian Ciupitu 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.