大容量.tgzからファイルを効率的に削除する

大容量.tgzからファイルを効率的に削除する

gzipで圧縮されたtar-ballcompressedArchive.tgz(+ 100ファイル、+ 5GBの合計)があるとしましょう。

指定されたファイル名パターン(たとえば、プレフィックス* .jpg)に一致するすべてのエントリを削除し、残りをgzip:ed tar-ballに保存する最も簡単な方法は何ですか?

古いアーカイブを置き換えたり、新しいアーカイブを作成したりするのが最も速いことは重要ではありません。

答え1

GNUを使用すると、tar次のことができます。

pigz -d < file.tgz |
  tar --delete --wildcards -f - '*/prefix*.jpg' |
  pigz > newfile.tgz

そしてbsdtar

pigz -d < file.tgz |
  bsdtar -cf - --exclude='*/prefix*.jpg' @- |
  pigz > newfile.tgz

pigzマルチスレッドバージョンですgzip)。

次のようにファイル自体を上書きできます。

{ pigz -d < file.tgz |
    tar --delete --wildcards -f - '*/prefix*.jpg' |
    pigz &&
    perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file.tgz

しかし、これは非常に危険です。特に、結果が元のファイルよりも圧縮されていない場合(この場合、2番目のファイルは最初のファイルがまだpigz読み取られていないファイル領域を上書きする可能性があります)。

答え2

単純なアプローチを過小評価しないでください。あなたの目的に合わせて十分速いかもしれません。そしてAVFSアーカイブにディレクトリとしてアクセスします。

cd ~/.avfs/path/to/original.tar.gz\#
pax -w -s '/^.*\.jpg$//' | gzip >/path/to/filtered.tar.gz        # POSIX
tar -czf /path/to/filtered.tar.gz -s '/^.*\.jpg$//' .            # BSD
tar -czf /path/to/filtered.tar.gz --transform '/^.*\.jpg$//' .   # GNU

より原始的なツールを使用して、最初に除外されたファイルからファイルを抽出し、.jpg新しいアーカイブを作成します。

mkdir tmpdir && cd tmpdir
<original.tar.gz gzip -d | pax -r -pe -s '/^.*\.jpg$//'
pax -w . | gzip >filtered.tar.gz
cd .. && rm -rf tmpdir

タールに以下がある場合--exclude

mkdir tmpdir && cd tmpdir
tar -xzf original.tar.gz --exclude='*.jpg'
tar -czf filtered.tar.gz .
cd .. && rm -rf tmpdir

ただし、rootとして実行しないと、ファイルの所有権とスキーマが破損する可能性があります。最良の結果を得るには、高速ファイルシステムの一時ディレクトリであるtmpfsを使用してください(ファイルシステムが十分に大きい場合)。

パススルー(アーカイブファイルの読み取りやアーカイブファイルの書き込み)として機能するアーカイバのサポートは制限される傾向があります。GNU tarはアーカイブからメンバーを削除できます。そして--deleteジョブオプション(「このオプションは、からのフィルタとして機能すると正しく機能することが報告されています--delete。」)これが最良の選択肢かもしれません。tarstdinstdout

数行のPythonコードで強力なアーカイブフィルタを作成できます。それtarfileライブラリは検索できないストリームから読み書きでき、Pythonで任意のコードを使用してフィルタリング、名前変更、変更などを実行できます。

#!/usr/bin/python
import re, sys, tarfile
source = tarfile.open(fileobj=sys.stdin, mode='r|*')
dest = tarfile.open(fileobj=sys.stdout, mode='w|gz')
for member in source:
    if not (member.isreg() and re.match(r'.*\.jpg\Z', member.name)):
        sys.stderr.write(member.name + '\n')
        dest.addfile(member, source.extractfile(member))
dest.close()

答え3

Mac OSXでtarを使用すると、次のことができます。

tar -czf b.tgz --exclude '*.jpg' @a.tgz
mv b.tgz a.tgz

答え4

私は使用する:

tar -xvf myLarge.gz --exclude "prefix" | tar -czvf myLarge.gz -T -

これは次のことを行います。

  1. 「を含むファイルを除くすべてのファイルを抽出します。プレフィックス
  2. -T -)残りの内容をtarにパイプし、myLarge.gzを再圧縮します。

関連情報