有这样一行简单的代码:
user@Host:~$ ls -> fileA fileB
user@Host:~$ [[ -d $dir_name ]] && rm * # $dir_name does not exist, empty variable
user@Host:~$ ls -> fileA fileB #does not delete anything, as expected
user@Host:~$ [ -d $dir_name ] && rm *
user@Host:~$ ls -> #empty, although there is a test, all files are deleted, why?
我知道双括号[[
是 bash 的扩展(或由 ksh 引入),但是为什么在上面的例子中明显的退出状态为 0 时标准测试没有关闭?
答案1
正确的用法是[ -d "$dir_name" ]
。
通常情况下,不带引号的变量会进行分词:如果$dir_name
包含空格,它将扩展为多种的结果命令的 argv[] 数组中的参数;如果是空字符串,则不会产生任何参数。同样的规则也适用于[
,它只不过是一个内置命令(实际上也是一个独立的可执行文件)。
因此,您的第二条命令与 不同[ -d "" ]
——它实际上扩展为[ -d ]
。由于参数数量不同,它变成了一个完全不同的表达式——-d
不再表示“目录存在”测试,而是本身用作“字符串参数非空”测试的字符串参数(如[ foo ]
),当然会成功。
然而,这些规则不要应用于[[
,它会受到 shell 解析器的特殊处理。 内部变量扩展的[[
工作方式不同 - 在许多情况下,参数被隐式地“双引号”,因此[[ -d $foo ]]
和[[ -d "$foo" ]]
是等效的。 这就是差异的来源。
也可以看看: