Почему моя переменная не увеличивается в цикле bash while? - PullRequest
15 голосов
/ 21 февраля 2011

Я довольно новичок в скриптах bash.Кажется, я не могу получить правильное значение моих переменных подсчета для отображения в конце цикла while в моем скрипте bash.

Справочная информация: у меня довольно простая задача: я хотел быпередать 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

Что случилось со значениями этих переменных?У Google было много предложений сомнительного качества, и я думаю, что я мог бы заставить его работать с немного большим количеством поиска, но краткое объяснение того, что я делаю неправильно, было бы очень полезно.

Ответы [ 3 ]

23 голосов
/ 21 февраля 2011

Это потому, что вы используете бесполезную команду cat с каналом, в результате чего создается подоболочка.Попробуйте без cat:

while read filename ; do
    N=$((N+1))
    ....
done < file
1 голос
/ 18 мая 2016

В качестве альтернативы, если вы хотите по какой-то причине оставить cat, вы можете исправить свой сценарий, просто добавив эту строку перед инструкцией cat:

shopt -s lastpipe 
0 голосов
/ 13 июня 2016

В более общем случае иногда требуется передать вывод команды.Вот пример, который использует процесс подстановки для линтинга файлов JavaScript, которые должны быть зафиксированы Git, и подсчитывает количество файлов, которые не удалось:

# $@ 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 || :
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...