for循环中变量不递增

for循环中变量不递增

我正在尝试打印工作目录中的目录数。由于某种原因,我的计数器没有增加。你能告诉我为什么吗?

#!/bin/bash
n=0
for afile in $(ls)
do
    if [ -d $afile ]
    then
      (( n ++ ))
    fi
done
echo There are $n directories under the current directory $(pwd).
exit 0

奇怪的是,这个程序似乎通过 ls ..(上目录)进行迭代

for myfile in $(ls ..)
do
    if [ -d "../$myfile" ]
    then
      echo "../$myfile (dir)"
    else
      echo ../$myfile
    fi
done
exit 0

答案1

要计算非隐藏目录(当前目录中)的数量,请使用bash

shopt -s nullglob
set -- */
printf 'There are %d non-hidden subdirectories in %s\n' "$#" "$PWD"

要包括隐藏目录的计数:

shopt -s dotglob nullglob
set -- */
printf 'There are %d subdirectories in %s\n' "$#" "$PWD"

这些代码的作用是扩展模式*/并计算模式扩展后的名称数量。该模式由于以斜杠结尾,因此将仅有的扩展为目录名称(或目录的符号链接的名称)。

目录名称将使用 分配给位置参数等$1,并且这些参数的数量由 shell 保留(因此不需要实际循环它们来计数)。$2set$#

如果您对bash数组感觉更舒服:

shopt -s dotglob nullglob
dirs=( */ )
printf 'There are %d subdirectories in %s\n' "${#dirs[@]}" "$PWD"

这本质上是同一件事,只不过它使用命名数组而不是位置参数。

dotglob中的 shell 选项将bash匹配*隐藏名称和非隐藏名称。 shellnullglob选项将使不匹配的模式扩展为空。

有关的:

答案2

您的代码对我来说工作正常,但其中存在一些错误,在某些情况下会失败(例如,如果文件名中包含空格)。

  • 首先,不要解析ls. 而是使用 glob 进行迭代。即,而不是$(ls),使用*
  • 读取变量时,应该引用它们,即使用"$foo"而不是$foo。如果不引用它们,shell 将在 IFS 上分割输出(即空格)。您可以使用脚本对此进行测试。包括一些没有空格的目录,然后用空格进行测试。仅计算前者。

这是固定代码:

#!/bin/bash
n=0
for afile in *
do
    if [ -d "$afile" ]
    then
      (( n ++ ))
    fi
done
echo There are $n directories under the current directory $(pwd).
exit 0

我不确定这是否显而易见,但脚本将在当前目录中运行。

相关内容