我正在尝试编写一个 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" ]
一些评论:
在 shell 中,空格很重要。如果希望 shell 识别 test 命令,
[
, 两边必须有空格[
。空格对于 shell 关键字来说并不重要,但是
[
,与 不同[[
, 是一个命令,而不是关键字。错误信息的含义
[0: command not found
是, 的"$#"
计算结果为 0,因此字符串["$#"
变成[0
,并且 bash 找不到名为 的命令[0
。在 bash 中可以使用
==
来判断字符串相等性。但是,它不可移植。在 POSIX 中, 中的正确相等运算符[...]
是=
。如果您有意运行脚本,这一点就变得非常重要或无意中,在像 这样的 POSIX shell 下dash
。
其他事宜
再次强调,空格很重要。当 shell 看到这个命令时:
output = "$($0 $x)"
它将尝试执行一个名为的命令
output
并为其提供两个参数,第一个是=
,第二个是 的结果"$($0 $x)"
。因此,正如 Gordon Davisson 指出的那样,该行应该替换为:output="$($0 $x)"
由于 周围没有空格
=
,因此 shell 会将其视为变量赋值。ls
该脚本尝试解析并输出这是不可靠的。在这种情况下,如果任何子目录名称包含空格,就会导致错误。正如 rici 指出的那样,该命令
directory="$(echo pwd)"
可能不会按照您的预期执行。观察:$ directory="$(echo pwd)" $ echo "$directory" pwd
此命令将字符串分配
pwd
给变量directory
。您可能想要当前工作目录,如下所示:directory=$(pwd)
但是,它比这更简单。在 Unix 中,当前工作目录始终是
.
:directory=.
还有其他原因导致此“如果-那么”语句无法达到人们的期望:
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)"
即使文件或目录名称包含空格或其他困难字符,也可以安全使用此方法。