私はbashスクリプトにかなり慣れていません。 bashスクリプトのwhile
ループの最後に表示するカウント変数の正しい値を取得できないようです。
背景:私にはかなり単純なタスクがあります。ファイルパスのリストを含むテキストファイルをbashスクリプトに渡し、それらのファイルの存在をチェックして、既存/欠落ファイルの数をカウントしたいと思います。カウント部分を除いて、ほとんどのスクリプトを機能させました。
N=0
correct=0
incorrect=0
cat $1 | while read filename ; do
N=$((N+1))
echo "$N"
if ! [ -f $filename ]; then
incorrect=$((incorrect+1))
else
correct=$((correct+1))
fi
done
echo "# of Correct Paths: $correct"
echo "# of Incorrect Paths: $incorrect"
echo "Total # of Files: $N"
5つのファイルのリストがあり、そのうち4つが存在する場合、次の出力が得られるはずです(echo
ループ内のwhile
コマンドに注意してください)。
1
2
3
4
5
# of Correct Paths: 4
# of Incorrect Paths: 1
Total # of Files: 5
代わりに、次のようになります。
1
2
3
4
5
# of Correct Paths: 0
# of Incorrect Paths: 0
Total # of Files: 0
これらの変数の値はどうなりましたか?グーグルは疑わしい品質の提案をたくさん持っていて、もう少し検索することでそれを機能させることができると思いますが、私が間違っていることの簡単な説明は非常に役に立ちます。
これは、パイプで役に立たないcat
コマンドを使用しているため、サブシェルが作成されているためです。 cat
なしで試してみてください:
while read filename ; do
N=$((N+1))
....
done < file
または、何らかの理由でcat
を保持したい場合は、cat
命令の前に次の行を追加するだけでスクリプトを修正できます。
shopt -s lastpipe
より一般的には、コマンドの出力をパイプ処理したい場合があります。 プロセス置換 を使用してGitによってコミットされようとしているJavaScriptファイルをリントし、失敗したファイルの数をカウントする例を次に示します。
# $@ glob
git-staged-files() {
git diff --cached -C -C -z --name-only --relative --diff-filter=ACMRTUXB "$@"
}
# $@ name
map() { IFS= read -rd $'\0' "$@"; }
declare -i errs=0
while map file; do
echo "Checking $file..."
git show ":$file"|
eslint --stdin --stdin-filename "$file" || ((++errs))
done < <(git-staged-files \*.js)
((errs)) && echo -en "\e[31m$errs files with errors.\e[00m " >&2 || :