好吧,我有这个代码
dirname=
if [ -d $dirname ];
then
cd $dirname && rm *
fi
正如你所看到的,我有这个空变量,我想知道为什么当使用像这样带有单方括号的空变量时,它会删除所有用户的主目录文件
如果我使用双方括号,它不会删除用户的主目录文件
像这样
dirname=
if [[ -d $dirname ]];
then
cd $dirname && rm *
fi
我已经阅读了使用单方括号和双方括号时的差异语法
我可以知道为什么会发生这种情况吗?
答案1
当cd
不传递参数时,它将更改为默认目录(大多数情况下是用户的主目录$HOME
)。
这个问题有趣的部分是,当您不向-d
bashtest
或[
内置操作符传递任何内容时,bash 似乎会以 0 退出(在我看来,这是意外的)。
当您设置dirname
为空变量时,您实际上是在运行以下命令:
if [ -d ]; then
cd && rm *
fi
对我来说,令人惊讶的是该块内的代码if
被执行,但我可以在我的机器上确认它确实如此。正如上面的注释所解释的,test
不再将 解释-d
为运算符,而只是返回 0,因为它是一个非空字符串。帮助防止这种行为的一种方法是确保引用变量:
if [ -d "$dirname" ]; then
cd "$dirname" && rm *
fi
在这种情况下,如果$dirname
为空,您将传递""
给-d
正确计算非零退出代码的运算符,因此块内的代码不会被执行。
答案2
未引用的内容$dirname
会受到分词的影响,如果它是空的,它就会被分割已删除,在 和 中[ -d $dirname ]
,cd $dirname
只留下[ -d ]
和cd
。
在第一个中,[
仅看到一个参数(在[
和之间]
),在这种情况下,测试是查看该参数是否为非空字符串。-d
是,所以测试为真。 (这类似于[ -z $var ]
测试是否$var
为空的方式,但[ -n $var ]
根本不起作用。)
至于cd
,普通文件cd
将更改为用户的主目录,因此这就是rm *
发生的地方。
使用 时[[ .. ]]
,不会发生分词,因为它[[
是一个特殊的 shell 结构,[
与常规命令不同。
解决办法是对变量扩展加双引号,出于各种原因,在大多数情况下您都会想要这样做。就像这样:
if [ -d "$dirname" ]; then
cd -- "$dirname" && rm ./*
fi
看: