我应该如何将多个压缩文件合并为一个存档?

jl6*_*jl6 11 tar compression

我有几百个.tar.xz几乎相同的文件(它们是每日数据库转储,数据库变化缓慢)。

我相信由于未压缩文件的相似性,它们会压缩得很好,并且小规模测试表明,压缩任意数量的这些未压缩文件会创建一个仅比其中一个稍大的存档。

我的问题是所有未压缩的文件都只有几 TB(压缩比约为 25:1),而且我没有那么多磁盘空间可用作工作区。

有没有一种方法可以一次处理单个压缩文件,将它们添加到单个存档中并保留将它们压缩在一起的好处?

Mic*_*mer 10

由于 tar 文件是一种流格式——您可以cat将它们中的两个放在一起并获得几乎正确的结果——您根本不需要将它们提取到磁盘来执行此操作。您可以(仅)解压缩文件,将它们连接在一起,然后重新压缩该流:

xzcat *.tar.xz | xz -c > combined.tar.xz
Run Code Online (Sandbox Code Playgroud)

combined.tar.xz将是组件 tarball 中所有文件的压缩 tarball,只是轻微损坏。要提取,您必须使用该--ignore-zeros选项(在 GNU 中tar),因为档案确实有一个“文件结束”标记,它将出现在结果的中间。但是,除此之外,一切都会正常工作。

GNUtar还支持一种--concatenate生成组合档案的模式。这具有与上述相同的限制 - 您必须使用--ignore-zeros来提取 - 但它不适用于压缩档案。您可以使用流程替换来构建一些东西来诱使它工作,但它很麻烦,甚至更脆弱。

如果文件在不同的 tar 文件中出现不止一次,这将无法正常工作,但无论如何你都会遇到这个问题。否则,这会给你想要的东西-管道输出经过xz是怎样tar呢压缩它的输出。


如果仅适用于特定tar实现的档案不足以满足您的目的,那么附加到档案中r是您的朋友:

tar cJf combined.tar.xz dummy-file
for x in db-*.tar.xz
do
    mkdir tmp
    pushd tmp
    tar xJf "../$x"
    tar rJf ../combined.tar.xz .
    popd
    rm -r tmp
done
Run Code Online (Sandbox Code Playgroud)

这一次只能提取一个档案,因此工作空间仅限于单个档案内容的大小。压缩正在流式传输,就像您一次制作最终存档一样,因此它将与以往一样好。你做了很多多余的解压缩和重新压缩,这会使它比cat版本慢,但生成的存档可以在没有任何特殊支持的情况下在任何地方工作。

请注意——取决于你到底想要什么——只需将未压缩的 tar 文件本身添加到存档中就足够了。它们将(几乎)完全像单个文件中的内容一样压缩,并且将减少每个文件的压缩开销。这看起来像:

tar cJf combined.tar.xz dummy-file
for x in db-*.tar.xz
do
    xz -dk "$x"
    tar rJf combined.tar.xz "${x%.xz}"
    rm -f "${x%.xz}"
done
Run Code Online (Sandbox Code Playgroud)

这在最终压缩大小方面效率稍低,因为流中有额外的 tar 标头,但可以节省一些时间来提取所有文件并将其重新添加为文件。您最终会combined.tar.xz包含许多(未压缩的)db-*.tar文件。