ワイルドカードを使用する関数でパスを使用する

ワイルドカードを使用する関数でパスを使用する

私たち全員が知っているように、ls解析の結果は次のとおりです。一般的に悪い考え1つの解決策は、lsの代わりにglobbingを使用してディレクトリ内のファイルを「安全に」繰り返すことです。

for path in /path/to/search/*; do
    ...
    # Do more filtering
    ...
    echo "$path"
done

この関数は、グローバルマッチングのいくつかの結果をさらにフィルタリングし、残りのパスを出力します。

しかし、このロジックを他の場所で再利用するには、関数を介してその出力を安全に使用して繰り返すことはできますか?

function myglob() {
    for path in /path/to/search/*; do
        ...
        # Do more filtering
        ...
        echo "$path"
    done
}

function myExample() {
    results=$(myglob)
    for i in "$results"; do
        echo "$i"
    done
}

それとも、常にグローバルロジックをコピーして内部ロジックを少し変更する必要がありますか?

答え1

いいえ、表示されたループ出力は問題を正確に複製し、ファイル名のバックスラッシュを解釈する可能性を追加するlsため、再利用できません。echo

対照的に、配列と名前参照を持つシェル言語を使用している場合(bash4.3+と同様)、これは少し異なる方法で実行できます。

myglob () {
   declare -n list="$1"

   list=( /path/to/search/* )
}

myexample () {
    local results=()
    myglob results

    for pathname in "${results[@]}"; do
        printf '%s\n' "$pathname"
    done

    # or shorter, just
    # printf '%s\n' "${results[@]}"
}

ここで、関数は名前参照変数であるmyglob変数の名前を使用します。listこれは、すべての使用がlist実際に名前付き変数を使用することを意味します。この関数は単にglobを拡張し、list配列のようにその中に結果を保存します。

その後、関数myexamplemyglob文字列を使用して呼び出されますresults。したがってlist、 の変数はmyglobそのresults変数を参照し、拡張パターンを保存します。

その後、関数はresultsアイテムの配列として引き続き使用されます。

myglobフィルタリングが必要な場合:

myglob () {
    declare -n list="$1"

    list=()
    for pathname in /path/to/search/*; do
        # decide whether to use "$pathname" or not
        # then, if it is to be used,
        list+=( "$pathname" )
    done
}

つまり、呼び出し元にアイテムを返すには、拡張パターンを繰り返してアイテムをリストに追加します。

関連情報