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


21

次のような行があります。

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

しかし、私は次のエラーを受け取りました:

xargs: argument line too long

私は混乱しています。の使用はxargs、この問題に正確に役立つと思われませんか?

注:-exec findで技術的に使用できることは知っていますが、上記が失敗する理由を理解したいと思います。なぜなら、私の理解はxargs、入力を実行可能な引数に管理可能なサイズに分割する方法を知っているはずだからです これは真実ではありませんか?

これはzshですべてです。

回答:


11

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 1設定しxargs、それはあなたがそれを単一の方法でを介してファイルを実行したいコマンドを呼び出していることになります。

したがって、xargs1000個のファイルを指定すると、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 {} +

ありがとう!"This approach shouldn't be used"代わりにどちらのアプローチを使用すべきかと言ったときは?う"find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir'"、より良い解決策になりますか?もしそうなら、この場合、パイプから取得した引数を入力するコマンドのどこをどのようにxargs知っていmvますか?(常に最後に配置しますか?)
アメリオバスケスレイナ

@ user815423426-だけでそれを行うのfind ... -exec ...がより良い方法であるか、使用xargsしたい場合でもfind ... | xargs ... mv -t ...大丈夫です。うん、それは常にそれらを最後に置きます。そのため、このメソッドにはが必要-tです。
slm

5

オプション-iはオプションの引数を取ります。後-iにスペースを入れるので、-iオプションへの引数はなく、したがって、後続-0のオプションxargsは6つのオペランドの2番目のオプションではありません{} -0 mv -t /some/path {}

オプションのみの場合-i、xargsは改行で区切られたファイル名のリストを期待していました。入力におそらく改行がなかったため、xargsは巨大なファイル名のように見えるものを受け取りました(nullバイトが埋め込まれていますが、xargsはそれをチェックしませんでした)。の出力全体を含むこの単一の文字列は、findコマンドラインの最大長よりも長かったため、「コマンドラインが長すぎます」というエラーが発生しました。

あなたのコマンドはの-i{}代わりに機能し-i {}ます。また、あなたが使用している可能性が-I {}-Iに似てい-iますが、次の引数が渡さので、必須の引数を取るxargsの引数として使用されている-Iオプション。その後、その後の引数-0はオプションとして解釈され、以下同様です。

ただし、まったく使用-I {}しないでください。を使用する-Iと、次の3つの効果があります。

  • -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 {} +

0

bash forループを使用してみてください。

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

または、何が起こっているかを見たい場合:

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

0

あなたが魚の殻を使用しているときにこれを見ている場合。
これは、魚が置換文字列を拡張する方法に関連しています{}

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

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

または、別の置換文字列を使用します

| xargs -I ! echo !
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.