find
シェルで定義した関数を実行する方法はありますか?
例えば:
dosomething () {
echo "Doing something with $1"
}
find . -exec dosomething {} \;
その結果は次のとおりです。
find: dosomething: No such file or directory
見る方法はありますかfind
?-exec
dosomething
シェル関数の実行方法を知っているのはシェルだけなので、関数を実行するにはシェルを実行する必要があります。また、エクスポート用に関数を でマークする必要がありますexport -f
。そうしないと、サブシェルはそれらを継承しません。
export -f dosomething
find . -exec bash -c 'dosomething "$0"' {} \;
find . | while read file; do dosomething "$file"; done
Jac の答えは素晴らしいですが、簡単に克服できる落とし穴がいくつかあります。
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
これは区切り文字として改行の代わりに null を使用するため、改行を含むファイル名が機能します。また、バックスラッシュのエスケープを無効にするフラグも使用し-r
ます。これがないと、ファイル名のバックスラッシュは機能しません。またIFS
、名前の潜在的な末尾の空白が破棄されないようにクリアします。
{}
以下に示すように引用符を追加します。
export -f dosomething
find . -exec bash -c 'dosomething "{}"' \;
find
これにより、名前に括弧が含まれるファイルなど、によって返される特殊文字によるエラーが修正されます。
効率を上げるためxargs
に結果をまとめて処理する人が多いですが、非常に危険です。find
そのため、結果を一括で実行する別の方法が に導入されました。
ただし、この方法には、コマンドの最後にあるPOSIX の要件など、いくつかの警告が伴う場合があることに注意find
してください。{}
export -f dosomething
find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} +
find
は多くの結果を引数として の 1 回の呼び出しに渡しbash
、for
-loop はそれらの引数を繰り返し処理し、それらのdosomething
それぞれに対して関数を実行します。
上記の解決策では、 で引数が開始されます。これが(を表す)$1
がある理由です。_
$0
同様に、受け入れられた上位の回答は次のように修正する必要があると思います
export -f dosomething
find . -exec bash -c 'dosomething "$1"' _ {} \;
引数は常に で始まる必要があるため、これはより正気であるだけでなく、によって返されるファイル名がシェルにとって特別な意味を持つ場合、 $1
using$0
によって予期しない動作が発生する可能性があります。find
スクリプト自体を呼び出し、見つかった各項目を引数として渡します。
#!/bin/bash
if [ ! $1 == "" ] ; then
echo "doing something with $1"
exit 0
fi
find . -exec $0 {} \;
exit 0
スクリプトを単独で実行すると、探しているものが見つかり、各検索結果を引数として渡して自分自身を呼び出します。スクリプトが引数付きで実行されると、引数でコマンドを実行してから終了します。
そのように関数を実行することはできません。
これを克服するには、関数をシェル スクリプトに配置し、それを呼び出すことができます。find
# dosomething.sh
dosomething () {
echo "doing something with $1"
}
dosomething $1
これを find で次のように使用します。
find . -exec dosomething.sh {} \;
関数を別のファイルに入れfind
て、それを実行します。
シェル関数は、それらが定義されているシェルの内部にあります。find
それらを見ることができなくなります。
直接ではありません。Find は、シェルではなく、別のプロセスで実行されています。
関数と同じ仕事をするシェルスクリプトを作成し、それを見つけることができます-exec
。
-exec
私は完全に使用を避けます。xargsを使用します。
find . -name <script/command you're searching for> | xargs bash -c