@StephaneChazelas はこの Q&A に対して次の解決策を投稿しました:「find -exec {} +」の使用時に問題が発生しています。
$ find . -iname "*.extension" -exec sh -c '
exec <command> "$@" <additional parameters>' sh {} +
ここでは一体何が起こっているのでしょうか? 具体的には、最後の部分は何をsh {}
するのでしょうか? これは、find-exec
コマンドを鎮静化させて、何かを行う (NOOP) ようにするためだけのように思えます。
簡単にecho {}
そこに置くことができ、問題なく動作するようです。
答え1
構文は次のとおりです。
find ... -exec cmd {} +
find
は、条件に基づいて多数のファイルを検索し...
、cmd
そのファイル パスのリストを引数として、コマンドの引数のサイズ制限を超えない範囲で可能な限り多く実行します。
必要に応じて、ファイルのリストを分割してcmd
複数回呼び出すことがあります。たとえば、次のように呼び出すことになります。
cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321
これには、最後に記述する必要があるという制限があります{}
。たとえば、次のように記述することはできません。
find ... -exec cmd {} other args +
';'
の代わりに を使用することもできます'+'
。
あなたは書ける:
find ... -exec echo foo {} +
だがしかし:
find ... -exec echo {} foo +
したがって、ファイル リストの後にいくつかの追加の引数を追加する必要がある場合はcmd
、シェルを呼び出す必要があります。(シェルを呼び出す必要があるその他の理由としては、リダイレクト、パイプ、一部の文字列拡張などのシェル機能を使用する必要がある場合が挙げられます。)
ではsh -c 'inline-script' x a b c
、 に対してinline-script
、$0
はx
、$1
はa
、$2
ですb
... であり"$@"
、3 つの引数 a、b、c のリストも同様です。したがって、 では次のようになります。
find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +
のためにインラインスクリプト、$0
(たとえばエラー メッセージを表示するときに使用されます)は に設定されfind-sh
、"$@"
ファイルのリスト(何にfind
展開されるか{}
)になります。
exec
シェルの特別な組み込み関数を使用すると:
find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +
を実行するために追加のプロセスをフォークするのではなくcmd
、同じプロセスでそれを実行するようにシェルに指示します (実行中のシェル プロセスをそのコマンドに置き換えます)。 などの一部のシェルや のzsh
実装では、ksh
インライン スクリプトの最後のコマンドに対して暗黙的にこれを実行します (bash
ここでのようにインライン スクリプトにコマンドが 1 つしかない場合も含みます)。