find + xargs: 引数行が長すぎます。

find + xargs: 引数行が長すぎます。

次の行があります。

find /foo/bar -name '*.mp4' -print0 | xargs -i {} -0 mv -t /some/path {}

ただし、次のエラーが発生します。

xargs: argument line too long

混乱しています。 Shouldを使用すると、xargsこの問題を解決するのに役立ちますか?

メモ:技術的にはfindを使用できることを知っていますが、-exec上記の方法が失敗した理由を知りたいです。xargsこれは、入力をジョブパラメータに合わせて管理可能なサイズに分割する方法を知る必要があるためです。これは本当ではないか?

それはすべてzshについてです。

答え1

まず、この-iスイッチは廃止されました。

-i[replace-str]
     This  option  is a synonym for -Ireplace-str if replace-str is specified. 
     If the replace-str argument is missing, the effect is the same as -I{}. 
     This option is deprecated; use -I instead.

だから、あなたのコマンドをこれに変更したときに動作しました。

$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}

はい

$ find . -print0 | xargs -I{} -0 echo {}
.
./.sshmenu
./The GIT version control system.html
./.vim_SO
./.vim_SO/README.txt
./.vim_SO/.git
./.vim_SO/.git/objects
./.vim_SO/.git/objects/pack
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.idx
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.pack
./.vim_SO/.git/objects/info
./.vim_SO/.git/refs
./.vim_SO/.git/refs/tags
...

使用-I{}

このコマンド構成を実行した後は、この方法を使用しないでください。

$ find -print0 ... | xargs -I{} -0 ...

xargs-xおよび に対してこれらのスイッチを暗黙的にオンにします-L 1。単一の方法でファイルを実行したいコマンドを呼び出すように設定します-L 1xargs

xargsしたがって、1000個のファイルを提供すると、mvコマンドが1000回実行されるため、ここで使用する目的は失われます。

それでは、どのような方法を使うべきですか?

次のように xargs を使用してこれを行うことができます。

$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path

または、ちょうどすべてを探してください:

$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +

答え2

このオプションはオプションの-iパラメータを使用します。後にスペースを入れたため、オプションには引数が-iない-iため、後続のオプションは6つのオペランドの2番目ではなく6つのオペランドの2番目-0です。xargs{} -0 mv -t /some/path {}

optionsのみを使用する場合、-ixargsは改行で区切られたファイル名のリストを期待します。入力に改行文字がない可能性があるため、xargsは大きく見えるファイル名を受け取ります(NULLバイトが含まれていますが、xargsはこれを確認しません)。出力全体を含む単一の文字列がfind最大コマンドライン長より長く、「コマンドラインが長すぎます」というエラーが発生します。

コマンドは-i{}代わりにを使用します-i {}。または-I {}-Iに似ています-iが、必須の引数を使用してに渡され、次の引数がオプションの引数としてxargs使用されます-I。これにより、次のパラメータが-0オプションとして解釈されます。

しかし、-I {}まったく使用しないでください。使用には-I3つの機能があります。

  • -I見積処理を終了すると-0完了です。
  • -I置換する文字列を{}デフォルト値に変更します。
  • -Iコマンドが各入力レコードに対して個別に実行されるようにします。これは、コマンド(mv -t)が呼び出しごとに複数のファイルを処理するように特別に設計されているため、ここでは役に立ちません。

あきらめる-I-i完全に

find /foo/bar -name '*.mp4' -print0 | xargs -0 mv -t /some/path {}

または、xargsを削除して次を使用します-exec

find /foo/bar -name '*.mp4' -exec mv -t /some/path {} +

答え3

bash forループを試してください:

for FILE in *.mp4 ; do rm $FILE ; done

または何が起こっているかを確認するには、次の手順を実行します。

for FILE in *.mp4 ; do echo Removing $FILE ; rm $FILE ; done

答え4

使用中にこの内容を見ると魚の皮
これは、魚が交換用の行を拡張する方法に関連しています。{}

Fishを使用している場合は、代替文字列をエスケープする必要があります。\{\}

| xargs -I \{\} echo \{\}

または、別の代替文字列を使用してください。

| xargs -I ! echo !

関連情報