これは、「find…-exec sh -c '…' sh {} +」を使用してコマンドをどのように機能させるのですか?


8

@StephaneChazelasがこのQ&Aに次の解決策を投稿しました:「find -exec {} +」の使用に問題があります

$ find . -iname "*.extension" -exec sh -c '
  exec <command> "$@" <additional parameters>' sh {} +

ここで何が起こっているのですか?具体的には、最後sh {}は何をしますか?それは、-exec何かすることがあるように、NOOPであるように、findのコマンドを鎮静化するためだけにあるかのようです。

私はecho {}そこに簡単に置くことができ、それはうまく機能しているようです。

回答:


9

構文は次のとおりです。

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...ので、"$@"a、bおよびc:それらの3つの引数のリストです。だから:

find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +

以下のためにインラインスクリプト$0(エラーメッセージを表示する際に、インスタンスのために使用されている)に設定されているfind-shし、"$@"(どのようなファイルのリストでfind展開さ{}に)。

execシェルの特別な組み込みを使用することにより:

find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +

実行する余分なプロセスをforkするのではcmdなく、同じプロセスで実行するようにシェルに指示します(実行中のシェルプロセスをそのコマンドで置き換えます)。のような一部のシェルbashzshおよびの一部の実装はksh、スクリプトの最後のコマンドに対して暗黙的にそれを実行します。


そこでexecの代わりにサブシェルを使用できますか?-exec sh -c '(cmd1; cmd2;)' find-sh {} +
slm

だから私があなたを正しく理解していればfind-sh {}、sh -c '...'コマンドの引数は正しいですか?
slm

@slmは、引数としてfind呼び出し/bin/shます("sh", "-c", "...", "find-sh", "./file1", "./file2"...). And inside ... , that maps (the shells maps that) to $ 0`で"find-sh"あり、位置パラメータ($1$2... インラインスクリプトへの引数)は./file1./file2です。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.