"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

1つの制限は、これが{}最後でなければならないということです。たとえば、次のように書き込むことはできません。

find ... -exec cmd {} other args +

';'代わりに使用できるように'+'

書くことができます:

find ... -exec echo foo {} +

しかし:

find ... -exec echo {} foo +

したがって、ファイルリストの後にいくつかの追加パラメータを追加する必要がある場合は、cmdシェルを呼び出す必要があります。 (シェルを呼び出す必要がある他の理由は、リダイレクト、パイプ、一部の文字列拡張などのシェル機能を使用する必要があるときです...)

では、is、is、is...:a、b、cという3つの引数リストsh -c 'inline-script' x a b cについても同様です。だから:inline-script$0x$1a$2b"$@"

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つしかない場合でも同様です)。

おすすめ記事