「find ... -exec sh -c '...' sh {} +」を使用したこの find コマンドはどのように機能しますか?

「find ... -exec sh -c '...' sh {} +」を使用したこの find コマンドはどのように機能しますか?

@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$0x$1a$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 つしかない場合も含みます)。

関連情報