为什么我的变量似乎在我的bash循环中增加?

时间:2011-02-21 00:36:33

标签: bash shell variables scripting

我是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

这些变量的值发生了什么变化?谷歌提出了许多质量有问题的建议,我想我可以通过更多的搜索来解决这个问题,但对我做错了什么的简要解释会非常有帮助。

3 个答案:

答案 0 :(得分:23)

这是因为您正在使用带有管道的无用cat命令,从而导致创建子shell。不使用cat

尝试
while read filename ; do
    N=$((N+1))
    ....
done < file

答案 1 :(得分:1)

或者,如果由于某种原因想要保留cat,只需在cat指令之前添加此行即可修复脚本:

shopt -s lastpipe 

答案 2 :(得分:0)

更一般地说,有时您想管道输出命令。这是一个使用process substitution来提交即将由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 || :