gzip圧縮されたtar-ball compressArchive.tgz(+100ファイル、合計+ 5gb)があると仮定します。
たとえば、prefix * .jpgなどの特定のファイル名パターンに一致するすべてのエントリを削除し、gzip:ed tar-ballに残りを保存する最も速い方法は何ですか?
古いアーカイブを置き換えるか、新しいアーカイブを作成するかは重要ではありません。
gzip圧縮されたtar-ball compressArchive.tgz(+100ファイル、合計+ 5gb)があると仮定します。
たとえば、prefix * .jpgなどの特定のファイル名パターンに一致するすべてのエントリを削除し、gzip:ed tar-ballに残りを保存する最も速い方法は何ですか?
古いアーカイブを置き換えるか、新しいアーカイブを作成するかは重要ではありません。
回答:
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
のファイルは最初のファイルがまだ読み取っていないファイルの領域を上書きする可能性があります)。
簡単な方法を軽視しないでください:それはあなたの目的のために十分に速いかもしれません。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
ときのオプションが正しく動作することが報告されているtar
から、フィルタとして機能stdin
するstdout
。」)、それはおそらくあなたの最良の選択肢です。
数行の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()
tar
すると、p
オプションを追加できます。
これを行うには、おそらくローカルディレクトリにある.tgzファイルのすべての内容を抽出し、不要なファイルを消去してから.tgzを再圧縮する必要があります。
それは長く、十分な空きディスク容量が必要ですが、私の知る限り、他に方法はありません。
/tmpdir/withalotofspace
十分な空き領域があるようなパスが既にある場合(を使用して確認してください df -h /tmpdir/withalotofspace
)、次のようなことができます。
$ cd /tmpdir/withalotofspace
$ tar -xvfz /path/to/compressedArchive.tgz
$ find /tmpdir/withalotofspace/ -type f -iname '*.jpg' -delete
$ tar -cvzf /path/to/purgedcompressedArchive.tgz .
@Gillesの回答が気に入っていますが、さらに簡略化できる点が異なります。解凍後、たとえばgunzip foo.tgz
、ファイルはになりfoo.tar
、ファイルはで削除できますtar -f foo.tar --delete file|directory
。以下は、tarファイルからディレクトリを削除する例です。
phablet@ubuntu-phablet:~/Downloads$ tar -cvf moo.tar moo1/
moo1/
moo1/moo2/
moo1/moo2/moo3/
moo1/moo2/moo3/moo4/
moo1/moo2/moo3/moo4/moo5/
phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar
moo1/
moo1/moo2/
moo1/moo2/moo3/
moo1/moo2/moo3/moo4/
moo1/moo2/moo3/moo4/moo5/
phablet@ubuntu-phablet:~/Downloads$ tar -f moo.tar --delete "moo1/moo2/moo3"
phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar
moo1/
moo1/moo2/
特定のファイルタイプはで見つけることができますtar -tf foo.tar|egrep -i '.jpg$'
。