次のような行があります。
find /foo/bar -name '*.mp4' -print0 | xargs -i {} -0 mv -t /some/path {}
しかし、私は次のエラーを受け取りました:
xargs: argument line too long
私は混乱しています。 xargs
の使用は、この問題に正確に役立つはずではありませんか?
注:技術的に-exec
in findですが、xargs
は入力を実行可能な引数に管理可能なサイズに分割する方法を知っているはずなので、上記が失敗する理由を理解したいと思います。これは本当ではないですか?
これはすべてzshの場合です。
まず、-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
を構成して、単一の方法でファイルを実行するコマンドを呼び出すようにします。
したがって、ここでxargs
を使用する目的は無効になります。1000個のファイルを指定すると、mv
コマンドが1000回実行されるためです。
次のようにxargsを使用して実行できます。
$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path
または、単にfind all it do all:
$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +
オプション-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 {} +
Bash forループを使用してみてください:
for FILE in *.mp4 ; do rm $FILE ; done
または、何が起こっているのかを見たい場合:
for FILE in *.mp4 ; do echo Removing $FILE ; rm $FILE ; done
fish Shell の使用中にこれが表示された場合。
これは、fishが置換文字列{}
を拡張する方法に関連しています
魚を使用している場合は、置換文字列\{\}
をエスケープする必要があります
| xargs -I \{\} echo \{\}
または別の置換文字列を使用する
| xargs -I ! echo !