web-dev-qa-db-ja.com

多くの圧縮ファイルを1つのアーカイブに結合するにはどうすればよいですか?

数百あります.tar.xzファイルはほとんど同じです(これらは毎日のデータベースダンプであり、データベースはゆっくりと変更されます)。

非圧縮ファイルは類似しているため、圧縮は非常にうまくいくと思います。小規模なテストでは、これらの非圧縮ファイルをいくつ圧縮しても、そのうちの1つよりわずかに大きいアーカイブしか作成されないことがわかっています。

私の問題は、すべての非圧縮ファイルが数テラバイト(圧縮比は約25:1)になることであり、作業領域として使用するためのディスク領域があまりありません。

個々の圧縮ファイルを一度に1つずつ処理して、それらを単一のアーカイブに追加し、それらを一緒に圧縮する利点を維持する方法はありますか?

10
jl6

Tarファイルはストリーミング形式であるため、2つをcat一緒に使用すると、ほぼ正しい結果を得ることができます。これを行うためにファイルをディスクに抽出する必要はまったくありません。ファイルを(のみ)解凍し、それらを連結して、そのストリームを再圧縮できます。

xzcat *.tar.xz | xz -c > combined.tar.xz

combined.tar.xzは、コンポーネントのtarball内のすべてのファイルの圧縮されたtarballであり、わずかに破損しています。アーカイブを抽出するには、 --ignore-zerosオプション (GNU tar)を使用する必要があります。アーカイブには「結果の中央に表示される「ファイルの終わり」マーカー。それ以外は、すべてが正しく動作します。

GNU tarは、結合アーカイブを作成するための --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

これは一度に1つのアーカイブのみを抽出するため、作業スペースは1つのアーカイブのコンテンツのサイズに制限されます。圧縮は、最終的なアーカイブを一度に作成した場合とまったく同じようにストリーミングされるため、これまでにないほど優れたものになります。過剰な解凍と再圧縮をたくさん行うと、これが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

これは、ストリームに余分なtarヘッダーがあるため、最終的な圧縮サイズの点で効率が少し低下しますが、すべてのファイルをファイルとして抽出および再追加する時間を節約できます。 combined.tar.xzには、多くの(非圧縮)db-*.tarファイルが含まれます。

10
Michael Homer