私たち全員が知っているように、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
対照的に、配列と名前参照を持つシェル言語を使用している場合(bash
4.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
配列のようにその中に結果を保存します。
その後、関数myexample
はmyglob
文字列を使用して呼び出されます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
}
つまり、呼び出し元にアイテムを返すには、拡張パターンを繰り返してアイテムをリストに追加します。