1

如果我有

if [ ! -e $dir ];
then
 mkdir $dir
fi 

工作,但不是

[[ ! -e $dir ]] || mkdir $dir 

为什么 ?

编辑 0

[[ ...我得到

 line 34: [[ !: command not found

编辑 1

bash --version
GNU bash, version 3.2.25(1)-release (i686-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

编辑 2

在某些情况下工作,在某些情况下不工作,两个连续的命令

[user@host ~]$ [ -e /tmp ] && date
-bash: [: missing `]'
[user@host ~]$ [ -e /tmp ] && date
mar jun 26 10:05:50 CLT 2012
4

3 回答 3

3

你应该使用

[ ! -e $dir ] && mkdir $dir

单个“[”是调用测试的快捷方式,因此适用测试语法。双“[[”改为使用bash的逻辑语法,这是完全不同的。

既然你想在测试返回真时执行命令,你应该使用“&&”——“||” 仅当测试返回 false 时,语法才会运行您的命令。

编辑:

检查 bash 手册页会发现条件表达式(使用 [[] 得到的)也理解 -e 语法。该部分没有提到“!” 否定结果,尽管在命令行上尝试它时它可以工作。我的猜测是,您的系统可能正在运行与评论者不同的 bash 版本,一个不理解“!”的系统。? test 的手册页清楚地表明“!” 受支持,因此在您的情况下,我将首先尝试使用 [ ] 并查看它是否有效,然后再进一步探索。

于 2012-06-25T21:09:46.200 回答
1

尤其是在编辑 2 之后,在我看来,这真的像是“有趣”字符的问题,要么是混入非打印字符,要么是看起来正常但奇怪的字符,如不间断空格。这些可能很难检测到;在编辑器中事情看起来完全正常,即使您查看带有类似内容的脚本cat -v也不会总是清楚地显示有趣的字符。如果您xxd的系统上有,这是一个非常好的方法来准确查看文件中的内容。这是此类问题的快速演示:

$ cat -v nbsptest 
#!/bin/bash -x
[ -e /tmp ] && date
[ -e /tmp ] && date
[ -e /tmp ] && date
$ ./nbsptest 
+ '[ -e' /tmp ']'
./nbsptest: line 2: [ -e: command not found
+ '[' -e '/tmp ]'
./nbsptest: line 3: [: missing `]'
+ '[' -e /tmp ']'
+ date
Sat Jun 30 10:53:56 PDT 2012
$ xxd nbsptest 
0000000: 2321 2f62 696e 2f62 6173 6820 2d78 0a5b  #!/bin/bash -x.[
0000010: c2a0 2d65 202f 746d 7020 5d20 2626 2064  ..-e /tmp ] && d
0000020: 6174 650a 5b20 2d65 202f 746d 70c2 a05d  ate.[ -e /tmp..]
0000030: 2026 2620 6461 7465 0a5b 202d 6520 2f74   && date.[ -e /t
0000040: 6d70 205d 2026 2620 6461 7465 0a         mp ] && date.

该脚本看起来完全正常cat -v(和more,,vi等),但前两个命令失败。 说明原因:第一个命令在和xxd之间有一个 UTF-8 不间断空格(这在十六进制列表中显示为 c2a0,在文本列表中),第二个命令在和之间有一个不间断空格(在文本列表中)。[-e[..-e/tmp]/tmp..]

显示-x(我曾经bash -x调用它,您也可以set -x按照@CodeGnome 的建议使用)也提示了正在发生的事情。对于第一个命令,它将其列为'[ -e' /tmp ']'-- 注意 周围的引号[ -e,这表明 shell 将所有这些都视为一个“单词”,这意味着它不认为它是中间的空格。类似地,第二个命令显示为'[' -e '/tmp ]'带有引号,表明它认为/tmp ]都是一个“单词”。

于 2012-06-30T17:59:49.747 回答
0

语法作品

至少,它对我有用。例如:

# Inverted logic. Returns false because directory exists.
$ [[ ! -e /tmp ]]; echo $?
1

你确定你使用的是 Bash 吗?检查您的外壳和版本。

$ echo $SHELL $BASH_VERSION
/bin/bash 4.2.10(1)-release

更好的方法

您的条件逻辑有点复杂。对于您想要做的事情,这是一种更简洁的语法:

dir=/tmp/foo
[[ -e "$dir" ]] || mkdir "$dir"

这在语义上更清晰,并且在没有倒置逻辑的情况下表达了意图。可能存在您需要反向测试的情况,但您的示例不是其中之一。

于 2012-06-25T21:11:30.883 回答