find -exec呼び出しでカスタム関数を実行する

find -exec呼び出しでカスタム関数を実行する

私はSolaris 10を使用しており、ksh(88)、bash(3.00)、およびzsh(4.2.1)を使用して以下をテストしました。

次のコードは結果を生成しません。

function foo {
    echo "Hello World"
}

find somedir -exec foo \;

findは複数のファイルと一致し(代替として表示されます-exec ...)、-print関数はfind外部から呼び出されると完全に機能します。

man findこのページの内容は次のとおりです-exec

-exec コマンド 実行されたコマンドが以下を返すと真です。
                     0 値は終了状態として使用されます。終わり
                     コマンドはエスケープ文字で区切る必要があります。
                     セミコロン(;)。コマンドパラメータ{}は
                     現在のパス名に置き換えます。もし
                     -execの最後の引数は{}です。
                     セミコロン(;)の代わりに+を指定してください。
                     コマンドはあまり頻繁に呼び出されません。
                     {} はパス名グループに置き換えられます。もし
                     このコマンドを呼び出すと返されます。
                     終了状態でゼロ以外の値を探します。
                     ゼロ以外の終了状態を返します。

おそらく次のようにすることができます。

for f in $(find somedir); do
    foo
done

しかし、フィールド区切り記号の問題に対処するのは怖いです。

呼び出しでシェル関数を呼び出すことは可能ですか(同じスクリプトで定義されているので、スコープの問題を心配する必要はありません)find ... -exec ...

私は両方とも試してみましたが、/usr/bin/find同じ/bin/find結果を得ました。

ベストアンサー1

Afunctionはシェル固有の関数なので、find -exec使用する前にシェルを作成し、そのシェルで関数を定義する必要があります。それは次のとおりです。

find ... -exec ksh -c '
  function foo {
    echo blan: "$@"
  }
  foo "$@"' ksh {} +

bash環境を介して機能をエクスポートできるのでexport -f(bashで)、次のことができます。

foo() { ...; }
export -f foo
find ... -exec bash -c 'foo "$@"' bash {} +

ksh88この関数は(環境を介さずに)エクスポートする必要がありますtypeset -fxが、実行中のシェーバンレススクリプトでのみ使用できるため、ksh使用できませんksh -c

別のオプションは、次のことです。

find ... -exec ksh -c "
  $(typeset -f foo)"'
  foo "$@"' ksh {} +

つまり、インラインスクリプトから関数typeset -f定義をダンプするために使用されます。他の機能を使用している場合は、その機能もダンプする必要があります。foofoo

ps -fあるいは、コマンドラインではなく環境変数を介して関数定義を渡すこともできます(出力に表示されます)。

FUNCDEFS=$(typeset -f foo) find ... -exec ksh -c '
  eval "$FUNCDEFS" &&
    unset -v FUNCDEFS &&
    foo "$@"' ksh {} +

unset -v FUNCDEFSこの機能で実行されるコマンドの環境を汚染しないようにfoo(存在する場合))

おすすめ記事