私は空白のあるパスを扱っています。
私はこのようにグローブを行います(2行目はグローブを設定します):
IFS=$'\n'
VAR="$1/"name_*
for file in $VAR; do
echo $file
grep ITEM "$file" | wc -l
done
ここで設定した値を使用すると、ファイル名のスペースでエラーが発生するのを防ぐことができ、ファイルを正しく表示できname_*
ます$1
。IFS
for
しかし今では、globと一致するファイルの総数を取得する簡単な方法が必要です。 forループでカウンタを使用できることはわかっていますが、パイプを使用してこれを行うことができたらと思いますVAR
。
ただしecho $VAR
、グローブを正常に実行しましたが、別のパスが空白になっている場合は、もはやアイテムを分割できないため、問題が発生します。IFSの仕組みなど、この動作をオーバーライドする方法はありますかfor
?
答え1
必要なものが区切り値のリストである場合は、文字列の使用/拡張を避ける必要があります。
基本的な解決策は、位置パラメータを設定することです。
set -- "$1"/name_*
スペースや改行文字(または他のほとんどの文字)があっても、一致する各ファイルを別々の場所引数として保持します。
shopt -s failglob
bashでは、glob()がどのファイルとも一致しない場合、またはglobがどのファイルとも一致できず、結果が得られたくない場合(ただしglob自体ではない)、スクリプトを停止するように設定する必要があります。スクリプトが停止しないようにするには、FAILGlobを設定しないでください。*
shopt -s nullglob
"$1"/name_*
ファイル数(glob の一致数を計算します。)今簡単に:
echo "$#"
位置パラメーターの数。
forループは次のように減ります。
for file
do echo "$file"
done
これにより、完全に分割される問題が回避されますIFS
。
$1
コードの挿入を防ぐには、外部値を引用する必要があります。
もecho "$file"
引用しなければならない。
配列にリストを割り当てることも可能です。
files=( "$1"/name_* )
これにより、位置パラメータが壊れるのを防ぎますが、構文がより複雑になります。配列の要素数は次のとおりです。
echo "${#files[@]}"
ループにはいくつかの変更が必要です。
for file in "${files[@]}"; do
echo "$file"
done
答え2
スペースの問題を解決できます。そして配列の使用に切り替えると、カウントが取得されます。
VAR=("$1/"name_*) # make array of filenames matching glob
echo "${#VAR[@]}" # number of elements in array
for file in "${VAR[@]}"; do # loop over individual elements of array
echo "$file"
grep ITEM "$file" -c # grep can count, wc isn't needed
done