使用不同的参数递归调用bash脚本

使用不同的参数递归调用bash脚本

我正在尝试编写一个 bash 脚本来计算给定目录和子目录中的所有文件,因此我写了这个:

#!/bin/bash

var=0
if ["$#" == "0"]
    directory="$(echo pwd)"
  then
    directory=$1
fi

echo $directory;
for x in `ls -l $directory | grep "^-" | tr -s ' ' | cut -d ' ' -f 9`;
do
var=$((var+1))
done

for x in `ls -l $directory | grep "^d" | tr -s ' ' | cut -d ' ' -f 9`;
do
output = "$($0 $x)"
done

var=$((var+output))
echo $var

但我得到了类似这样的信息:

./lala2
./lala2: line 4: [0: command not found

test
./lala2: line 4: [1: command not found
./lala2: line 4: [1: command not found

这是为什么?这些变量是全局变量吗?

答案1

代替:

if ["$#" == "0"]

和:

if [ "$#" = "0" ]

一些评论:

  1. 在 shell 中,空格很重要。如果希望 shell 识别 test 命令,[, 两边必须有空格[

    空格对于 shell 关键字来说并不重要,但是[,与 不同[[, 是一个命令,而不是关键字。

  2. 错误信息的含义[0: command not found是, 的"$#"计算结果为 0,因此字符串["$#"变成[0,并且 bash 找不到名为 的命令[0

  3. 在 bash 中可以使用==来判断字符串相等性。但是,它不可移植。在 POSIX 中, 中的正确相等运算符[...]=。如果您有意运行脚本,这一点就变得非常重要或无意中,在像 这样的 POSIX shell 下dash

其他事宜

  1. 再次强调,空格很重要。当 shell 看到这个命令时:

    output = "$($0 $x)"
    

    它将尝试执行一个名为的命令output并为其提供两个参数,第一个是=,第二个是 的结果"$($0 $x)"。因此,正如 Gordon Davisson 指出的那样,该行应该替换为:

    output="$($0 $x)"
    

    由于 周围没有空格=,因此 shell 会将其视为变量赋值。

  2. ls该脚本尝试解析并输出这是不可靠的。在这种情况下,如果任何子目录名称包含空格,就会导致错误。

  3. 正如 rici 指出的那样,该命令directory="$(echo pwd)"可能不会按照您的预期执行。观察:

    $ directory="$(echo pwd)"
    $ echo "$directory"
    pwd
    

    此命令将字符串分配pwd给变量directory。您可能想要当前工作目录,如下所示:

    directory=$(pwd)
    

    但是,它比这更简单。在 Unix 中,当前工作目录始终是.

    directory=.
    
  4. 还有其他原因导致此“如果-那么”语句无法达到人们的期望:

    if ["$#" == "0"]
        directory="$(echo pwd)"
      then
        directory=$1
    fi
    

    您可能想要移动该then语句并添加一条else语句:

    if [ "$#" = "0" ]
    then
        directory=.
    else
        directory="$1"
    fi
    

替代脚本

如果目标是计算目录及其所有子目录中的常规文件数量,请尝试:

echo "$(find "$directory" -type f -printf "1\n" | wc -l)"

即使文件或目录名称包含空格或其他困难字符,也可以安全使用此方法。

相关内容