毎日4〜100個の非常に大きなtar(〜20GB)アーカイブファイルを受け取ります。私は過去に、ファイルシステムに表示される各アーカイブをループして、次のようなことを行って、それらを連結しています。
/bin/tar -concatenate --file=allTars.tar receivedTar.tar
ただし、これに伴う問題は、tarファイルをどんどん連結するので、allTars.tar
の最後まで読み取って、再度連結を開始する必要があることです。別のtarファイルの追加を開始するのに20分以上かかる場合があります。それは遅すぎて、完全なallTars.tar
の合意された納期がありません。
私もtarコマンドに次のようなファイルのリストを渡そうとしました:
/bin/tar --concatenate --file=alltars.tar receiverTar1.tar receivedTar2.tar receivedTar3.tar...etc
これは非常に奇妙な結果をもたらしました。 allTars.tar
は予想されるサイズ(つまり、すべてのreceivedTar.tar
ファイルのサイズを合計したものに近い)ですが、allTars.tar
が解凍されたときにファイルを上書きするようです。
これらのすべてのtarファイルを1つのコマンドで連結する方法はありますか。そのため、毎回連結されるアーカイブの最後まで読み取る必要はありませんおよびすべてのファイル/データで正しくアンパックします?
これは役に立たないかもしれませんが、-i
オプションは、最終的なアーカイブから抽出するときに、タールを一緒にcat
するだけです。 tarファイルは、ヌルでいっぱいのヘッダーと、レコードの終わりまでのヌルパディングで終了します。 --concatenate
tarは、最終的なヘッダーの正確な位置を見つけるためにすべてのヘッダーを調べ、そこから上書きを開始する必要があります。
タールをcat
だけにすると、ヘッダー間に余分なヌルができます。 -i
オプションは、ヘッダー間のこれらのヌルを無視するようにtarに要求します。だからあなたはできる
cat receiverTar1.tar receivedTar2.tar ... >>alltars.tar
tar -itvf alltars.tar
また、あなたのtar --concatenate
例が機能するはずです。ただし、複数のtarアーカイブに同じ名前のファイルがある場合、結果のtarからすべてを抽出するときに、そのファイルを数回書き換えます。
この質問はかなり古いですが、次の情報をもっと早く見つけられるようになればよかったと思います。他の誰かがこれに遭遇した場合は、お楽しみください:
Jeffが上記で説明しているのは、gnu tarの既知のバグです(2008年8月に報告)。最初のアーカイブ(-f
オプションの後のアーカイブ)のみがEOFマーカーが削除されます。3つ以上のアーカイブを連結しようとすると、最後のアーカイブが非表示になります"ファイルエンドマーカーの後ろ。
Tarのバグです。末尾のゼロブロックを含むアーカイブ全体を連結するため、デフォルトでは、結果のアーカイブの読み取りは最初の連結後に停止します。
出典: https://lists.gnu.org/archive/html/bug-tar/2008-08/msg00002.html(およびそれに続くメッセージ)
バグの年数を考えると、修正されるかどうかは疑問です。影響を受けるクリティカルマスがあるとは思えません。
このバグを回避する最良の方法は、少なくともファイルシステム上の.tarファイルに対して-i
オプションを使用することです。
Jeffが指摘するように、tar --concatenate
は、次のアーカイブを連結する前にEOFに到達するまでに長い時間がかかる可能性があります。したがって、 untarするにはtar -i
オプションが必要です。以下をお勧めします。
を使用する代わりにtar --concatenate -f archive1.tar archive2.tar archive3.tar
実行する方が良いでしょうテープデバイスに書き込む場合は、cat archive2.tar archive3.tar >> archive1.tar
またはdd
にパイプします。また、このcouldは、新しいデータをテープに(過剰に)書き込む前にテープがゼロにならなかった場合、予期しない動作を引き起こすことに注意してください。そのため、私のアプリケーションで採用するアプローチは、質問の下のコメントで提案されているように、ネストされたtarです。
上記の提案は、次の非常に小さなサンプルベンチマークに基づいています。
time tar --concatenate -vf buffer.100025.tar buffer.100026.tar
real 65m33.524s
user 0m7.324s
sys 2m50.399s
time cat buffer.100027.tar >> buffer.100028.tar
real 46m34.101s
user 0m0.853s
sys 1m46.133s
Buffer。*。tarファイルのサイズはすべて100GBであり、システムは各呼び出しを除いてほとんどアイドル状態でした。時間差は非常に大きいため、サンプルサイズが小さいにもかかわらず、このベンチマークは有効であると個人的に考えていますが、これについては自由に判断でき、おそらくこのようなベンチマークをハードウェアで実行するのが最善です。
これは1行のコマンドではありませんが、/ usr/local/bin/tar_mergerにファイルを作成して実行可能にできる場合は、このpython3スクリプトを使用してtarをマージしてください。
マージしたいtarを最終的なファイルの名前のフォルダーに入れて、
tar_merger folder
フォルダー名で出力tarを作成し、フォルダー内のすべてのtarを調べて、ファイルを新しいtarに追加します。私にとっては、何千もの約1 GBのタールをマージすることで問題なく動作します。
#!/bin/env python3
# Merges many tars into a single one
# Wolfang Torres - [email protected]
from pathlib import Path
from tarfile import TarFile
from sys import argv
def cli(folder):
"""Merges all the tars in folder to a single tar"""
folder = Path(folder)
tar_path = folder.parent / f"{folder.name}.tar"
n = 0
sub_tars = Tuple(folder.glob("*.tar"))
total = len(sub_tars)
with TarFile(tar_path, "w", encoding="utf-8") as tar:
for sub_path in sub_tars:
n += 1
print(f"Adding tar {n}/{total} {sub_path.name}")
with TarFile(sub_path, "r", encoding="utf-8") as sub_tar:
for file in sub_tar:
data = sub_tar.extractfile(file)
tar.addfile(file, data)
print(f"Finished merging {n} Tars into {tar_path}")
if __name__ == "__main__":
if len(argv) < 2 or argv[1] in ("-h", "--help"):
print(f"{argv[0]} folder")
print()
print("Merges all the tars inside of `folder` to `folder.tar`")
else:
cli(argv[1])
すでに述べたように、ターゲットアーカイブファイルは、2番目のソースアーカイブが追加される前に最後まで読み取る必要があります。 GNU tarには-n
オプションは、ファイルがシーク可能であると想定するように指示します(tarはシークできないテープおよびストリームアーカイブ用に設計されていたことを思い出してください)。 GNU tarはおそらくファイルがシーク可能かどうかを自動検出するようにデフォルト設定されていますが、あなたなどの多くのユーザーは、-n
オプション:
tar -n --concatenate --file=target_file.tar other_file.tar
(執筆の時点で)tarのどのバージョンがこのコマンドで期待どおりに動作するかを確認できません。他のユーザーがこのソリューションを証明する能力を持っている場合は、以下にコメントしてください。この回答を適宜更新します。