web-dev-qa-db-ja.com

xargs / execには引数リストが長すぎます

私はCentOSサーバーで作業しており、何百万ものファイルを移動してまとめる必要があります。私は以下のようなものの多くの化身を試しましたが、それらはすべて引数リストが長すぎるエラーで失敗します。

コマンド:

find ./ -iname out.* -type f -exec mv {} /home/user/trash
find ./paramsFile.* -exec cat > parameters.txt 

エラー:

-bash: /usr/bin/find: Argument list too long
-bash: /bin/cat: Argument list too long

または

echo ./out.* | xargs -I '{}' mv /home/user/trash
(echo ./paramsFile.* | xargs cat) > parameters.txt  

エラー:

xargs: argument line too long
xargs: argument line too long              

2番目のコマンドも終了しませんでした。グロブについていくつか聞いたことがありますが、完全に理解できるかどうかはわかりません。ヒントや提案は大歓迎です!

2
ohblahitsme

あなたには複数の間違いがあります。 *グロブをエスケープする必要があります。 (ファイル名のセキュリティのために)引用符の間に{}を入れ、-exec\;で終了する必要があります。

find ./ -iname out.\* -type f -exec mv "{}" /home/user/trash \;
find -name ./paramsFile.\* -exec cat "{}" >> parameters.txt \;

ここでの問題は、*がディレクトリ内のすべてのファイルと一致しているため、エラーが発生することです。 findがシェルグロブの代わりにファイルを見つけた場合、xargsは、正しい長さの行を作成するために使用できる個々のファイル名を取得します。

4
Bernhard

これを試して:

find . -iname 'out.*' -type f -exec mv '{}' /home/user/trash \;
find . -name 'paramsFile.*' -print0 | xargs -0 cat >> parameters.txt

>>は、以前の呼び出しの結果を上書きせずに、catの複数の呼び出し(実際に膨大な数のファイルがある場合)が同じファイルに出力されるようにすることです。また、parameters.txtは空から始まります(または最初に削除します)。

1
jjlin

現時点では、非常に良い(つまりテスト済みの)答えを出すのに便利なボックスはありませんが、これは parallel の良い使い方だと思います。

私が正しく理解していれば、あなたの命令

find ./ -iname out.* -type f -exec mv "{}" /home/user/trash

1つの巨大なコマンドを作成しています:

mv out.1 out.2 out.3 out.4 ... out.10100942 /home/user/trash

代わりに、

find ./ -iname out.* -type f | parallel mv "{}" /home/user/trash

何百万もの小さなコマンドを実行します:

mv out.1 /home/user/trash
mv out.2 /home/user/trash
...

parallelのオプションのいくつか、具体的には -jおよび-i サーバーが予期せず過負荷にならないようにします。

PS。 @Bernhardのアドバイスに従ってください。特にユーザー入力にシェル変数を使用する場合は、引用してください。行う "{}"ではない{}

0
djeikyb