该[
命令是普通命令。尽管大多数shell都将其作为效率的内置组件提供,但它遵循了shell的常规语法规则。[
与完全等效test
,不同之处在于,最后一个参数[
要求]
为,test
而不需要。
双括号[[ … ]]
是特殊语法。之所以在ksh中引入了它们(几年后[
),因为[
正确使用可能会很麻烦,并且[[
允许使用shell特殊字符添加一些不错的新东西。例如,你可以写
[[ $x = foo && $y = bar ]]
因为整个条件表达式是由shell解析,而[ $x = foo && $y = bar ]
将首先分成两个命令[ $x = foo
和$y = bar ]
由分离的&&
操作者。类似地,双括号使诸如模式匹配语法之类的功能成为可能,例如[[ $x == a* ]]
,测试start的值是否x
以a
; 在单括号中,这将扩展a*
到名称列表a
在当前目录中开头的文件列表。双括号首先在ksh中引入,仅在ksh,bash和zsh中可用。
与其他大多数地方一样,在单括号内,您需要在变量替换周围使用双引号,因为它们只是命令的参数(碰巧是[
命令)。在双括号内,您不需要双引号,因为shell不会进行单词拆分或加修饰:它解析的是条件表达式,而不是命令。
但是[[ $var1 = "$var2" ]]
,如果要进行字节到字节的字符串比较,则需要在引号中做一个例外,否则$var2
将是一种匹配的模式$var1
。
您不能做的一件事[[ … ]]
就是使用变量作为运算符。例如,这是完全合法的(但很少有用):
if [ -n "$reverse_sort" ]; then op=-gt; else op=-lt; fi
…
if [ "$x" "$op" "$y" ]; then …
在你的例子中
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then …
内的命令if
是[
与所述4个参数-d
,/home/mazimi/VirtualBox
,VMs
和]
。shell解析-d /home/mazimi/VirtualBox
,然后不知道该怎么做VMs
。您将需要防止单词分裂${dir}
以获取格式正确的命令。
一般而言,除非知道要对结果执行单词拆分和遍历,否则始终在变量和命令替换周围使用双引号。不使用双引号安全的主要地方是:
- 在赋值中:(
foo=$bar
但请注意,您确实需要export "foo=$bar"
在数组赋值中或数组赋值中使用双引号,例如array=("$a" "$b")
);
- 在一个
case
声明:case $foo in …
;
- 里面除了上的右侧双括号
=
或==
操作符(除非你想要模式匹配)[[ $x = "$y" ]]
。
在所有这些中,使用双引号是正确的,因此您最好跳过高级规则并始终使用引号。