if/else 块的 else 部分永远不会在 Bash 脚本中运行

else part of an if/else block never runs in Bash script

在下面的函数中,如果目录中有任何文件,我会尝试打印文件名,如果没有,则尝试打印错误,但内部 if/else 块的其他部分会打印错误消息,永远不会运行。

应该是合乎逻辑的,但我想不通。

walk_dir () {
    shopt -s nullglob dotglob

    for pathname in ""/*; do
        if [ -d "$pathname" ]; then 
          printf "\nFiles under $(basename "$pathname")\n";
          printf "==========================================\n";

          walk_dir "$pathname";
        else 
          fc=$(find "$pathname" -maxdepth 1 -type f | wc -l);

          # Here is the problem
          if [ $fc -gt 0 ] && [ ! -z $fc ]; then 
            printf '%s\n' $(basename "$pathname");
          else 
            printf '\e[30mNo candidate file found.\e[39m\n';
          fi
        fi
    done
}

walk_dir有3个案例

  • 非空文件夹
  • 空文件夹
  • 普通文件
  • 忽略特殊文件,这里可能N/A。

当为非空文件夹调用时,walk_dir 将对任何子文件夹进行(递归)(第 7 行),然后在第 12 行打印每个常规文件的基本名称。

当使用空文件夹调用时,walk_dir 将不执行任何操作,因为“$1”/* 扩展为空列表。

当目录包含文件时,代码将 "count" 第 9 行中的文件数。这 l 只处理非目录 - 可能是文件(假设不是特殊设备等)。在这种情况下,它将对文件夹中的每个条目进行递归调用。

如果文件夹中有常规文件,代码将执行第 8 行的 find。在常规文件上将始终设置 fc="1",因此第 11 行的条件将始终为真,永远不会进入第 13 行的 else 部分。

     1  walk_dir () {
     2      shopt -s nullglob dotglob

     3      for pathname in ""/*; do
     4          if [ -d "$pathname" ]; then 
     5            printf "\nFiles under $(basename "$pathname")\n";
     6            printf "==========================================\n";

     7            walk_dir "$pathname";
     8          else 
     9            fc=$(find "$pathname" -maxdepth 1 -type f | wc -l);

    10            # Here is the problem
    11            if [ $fc -gt 0 ] && [ ! -z $fc ]; then 
    12              printf '%s\n' $(basename "$pathname");
    13            else 
    14              printf '\e[30mNo candidate file found.\e[39m\n';
    15            fi
    16          fi
    17      done
    18   }

根据@dash-o 的解释,我在遍历文件之前设置了 if 条件,结果如我所料。

walk_dir () {
    shopt -s nullglob dotglob

    fc=$(find "" -maxdepth 1 -type f | wc -l);

    if [ $fc -eq 0 ] || [ -z $fc ]; then 
      printf '\e[30mNo candidate file found.\e[0m\n';  
    fi

    for pathname in ""/*; do
        if [ -d "$pathname" ]; then 
          printf "\nFiles under $(basename "$pathname")\n";
          printf "==========================================\n";

          walk_dir "$pathname";
        else 
          printf '%s\n' $(basename "$pathname");
        fi
    done
}

评论太长了!

我不明白

的用法
fc=$(find "$pathname" -maxdepth 1 -type f | wc -l);

在那部分代码中,如果没有找到文件,$pathname 要么是一个文件(不是目录),要么是 for 循环的搜索模式。所以这段代码似乎更好:

if [[ -f $filename ]]
then
     # use input redirection to suppress filename
     fc=$(wc -l <"$filename")
else
     echo "not a plain file"
fi