findで関数を呼び出すときの変数範囲

findで関数を呼び出すときの変数範囲

BashスクリプトでFromを定義します。find問題は、変数の範囲が関数に拡張されないことです。関数内の変数にどのようにアクセスしますか?例は次のとおりです。

variable="Filename:"

myfunction() {
    echo $variable $1
}

export -f myfunction

find . -type f -exec bash -c 'myfunction "{}"' \;

これにより、「Filename:」文字列なしでファイル名が出力されます。

find見つかったすべてのファイルに対して呼び出され、findまだ変数を定義するために関数を呼び出すより良い方法はありますか?

答え1

あなたの質問に対する答えではありませんが、大丈夫です。いいえする:

find . -type f -exec bash -c 'myfunction "{}"' \;

移植性がないという事実に加えて、ファイル名がbashシェルコードとして解釈されるため、非常に危険です。たとえば、というファイルがある場合はどうなるか考えてみましょう$(rm -rf ~)。書き下ろす:

find . -type f -exec bash -c 'myfunction "$1"' find+bash {} \;

bashまたは、より良い方法は次のとおりです(ファイルごとに1つずつ実行したくない場合)。

find . -type f -exec bash -c 'for file do
  myfunction "$file"; done' find+bash {} +

それでは、トピックの質問に答えてみましょう。

次のことができます。

{ find . -type f -exec printf '%s\0' {} + | while IFS= read -ru3 -d '' file; do
  myfunction "$file"; done 3<&0 <&4 4<&-; } 4<&0

これにより、myfunction現在のシェル内で呼び出すことができるため、他のシェルをbashエクスポートまたは実行する必要はありません。myfunctionbash

GNU、busybox、一部のBSDなどの述語をfindサポートしている場合は、置き換えることができます。-print0find-exec printf '%s\0' {} +-print0

答え2

variable環境変数として宣言できます。

export variable="Filename:"

答え3

私はこれをします。

#!/bin/bash

myfunction() {
    local var="Filename: "
    local file=$1 
        echo "$var" "$file"
    }

export -f myfunction
    find . -type f -exec bash -c 'myfunction {}' \;

変数をローカル変数として宣言し、「{}」を最初の位置引数として関数に渡します$1

答え4

変数に代入すると、シェル変数で始まります。環境変数を子プロセスに渡すには、それをエクスポートする必要があります。

variable="Filename:"
export variable

export:と同じ行に課題を配置できますexport variable="Filename:"

この変数は起動シェルには表示されますが、find関数には表示されません。 Bashでは、関数をエクスポートすることもできます。 ksh、dash、およびその他の頻繁に使用されるシェルには、これらの可能性はありません。shより速く効率的だからです。

export -f myfunction    # bash only

{}ファイル名が英数字であることを知らない限り、(または)の文字列内で使用しないでください。ファイル名に特殊文字が含まれている場合、内部シェルはそれを解析します。代わりに、シェルのコマンドラインにファイル名を渡してください。find -exec …xargs …

find . -type f -exec bash -c 'for x; do myfunction "$x"; done' _ {} +

Bash 以外のシェルの場合は、内部シェルで関数を定義するか、そのコードを直接入力します。

あるいは、bashではfindの代わりに再帰ワイルドカードを使用できます。 Bashはディレクトリへのシンボリックリンクを通過します。

variable="Filename:"
myfunction () { … }
shopt -s globstar dotglob
for x in **/*; do
  if [[ -f $x ]]; then myfunction "$x"; fi
done

関連情報