web-dev-qa-db-ja.com

何百万ものファイルを見つけてtarするためのより効率的な方法

サーバーのコマンドラインプロンプトで2日間ジョブを実行しています。

find data/ -name filepattern-*2009* -exec tar uf 2009.tar {} ;

forever、そしていくつかかかります。はい、ターゲットディレクトリには何百万ものファイルがあります。 (各ファイルは、適切にハッシュされたディレクトリ構造でわずか8バイトです。)しかし、実行しているだけです...

find data/ -name filepattern-*2009* -print > filesOfInterest.txt

...たった2時間かそこらかかります。私の仕事が実行されている速度では、それは数週間週間終了しません。それは不合理に思えます。 これを行うためのより効率的な方法はありますか?多分もっと複雑なbashスクリプトを使用しますか?

二次的な質問は「なぜ私の現在のアプローチはとても遅いのですか?」

21
Stu Thompson

ファイルリストを作成した2番目のコマンドをすでに実行している場合は、-Tオプションを使用して、保存されたファイルリストからファイル名を読み取るようにtarに指示します。 1つのtarコマンドとNつのtarコマンドを実行する方がはるかに優れています。

20
frankc

1つのオプションは、cpioを使用してtar形式のアーカイブを生成することです。

$ find data/ -name "filepattern-*2009*" | cpio -ov --format=ustar > 2009.tar

cpioは、最上位ディレクトリではなく、stdinからのファイル名のリストをネイティブに処理するため、この状況に理想的なツールになります。

24
Matthew Mott

これは、xargsまたはexecを使用せずに必要なことを実行できるfind-tarの組み合わせです(これにより、顕著なスピードアップが得られるはずです)。

tar --version    # tar (GNU tar) 1.14 

# FreeBSD find (on Mac OS X)
find -x data -name "filepattern-*2009*" -print0 | tar --null --no-recursion -uf 2009.tar --files-from -

# for GNU find use -xdev instead of -x
gfind data -xdev -name "filepattern-*2009*" -print0 | tar --null --no-recursion -uf 2009.tar --files-from -

# added: set permissions via tar
find -x data -name "filepattern-*2009*" -print0 | \
    tar --null --no-recursion --owner=... --group=... --mode=... -uf 2009.tar --files-from -
8
bashfu

これにはxargsがあります:

find data/ -name filepattern-*2009* -print0 | xargs -0 tar uf 2009.tar

情報が少ないのでなぜ遅いのか推測するのは難しいです。ディレクトリの構造、使用するファイルシステム、作成時にどのように構成されたか。単一のディレクトリに何百万ものファイルがあることは、ほとんどのファイルシステムにとって非常に難しい状況です。

7
Michal Čihař

奇妙な(しかし正当な)文字(改行など)を含むファイル名を正しく処理するには、findの-print0を使用してファイルリストをfilesOfInterest.txtに書き込む必要があります。

find -x data -name "filepattern-*2009*" -print0 > filesOfInterest.txt
tar --null --no-recursion -uf 2009.tar --files-from filesOfInterest.txt 
3
bashfu

現在のやり方では、ファイルが見つかるたびにtarコマンドを呼び出していますが、これは驚くほど遅くはありません。印刷に2時間と、tarアーカイブを開くのにかかる時間を費やして、ファイルが古くなっていないかどうかを確認し、アーカイブに追加する代わりに、実際にはそれらの時間を掛け合わせています。すべての名前をバッチ処理した後、おそらくxargsを使用して呼び出しを実行した後、tarコマンドを1回呼び出す方がうまくいく可能性があります。ちなみに、星は引用符なしでシェルによって展開されるため、filepattern- * 2009 *ではなく 'filepattern- * 2009 *'を使用していることを願っています。

tarsplitterと呼ばれるこのためのユーティリティがあります。

tarsplitter -m archive -i folder/*.json -o archive.tar -p 8

8つのスレッドを使用して、「folder/*。json」に一致するファイルを「archive.tar」の出力アーカイブにアーカイブします。

https://github.com/AQUAOSOTech/tarsplitter

1
ruffrey