如果我有
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发布于 2012-07-01 01:59:50
特别是在编辑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说明了原因:第一个命令在[和-e之间有一个UTF-8不间断空格(在十六进制清单中显示为c2a0,在文本清单中显示为[..-e ),第二个命令在/tmp和]之间有一个不间断空格(在文本清单中显示为/tmp..])。
-x显示(我使用bash -x来调用它,您也可以按照@CodeGnome建议的那样使用set -x )也给出了一个关于发生了什么的提示。对于第一个命令,它将其列为'[ -e' /tmp ']' --请注意[ -e周围的引号,这表明shell将所有内容都视为一个“单词”,这意味着它不认为中间有空格。类似地,第二个命令显示为带有引号的'[' -e '/tmp ]',表示它认为/tmp ]都是一个“单词”。
发布于 2012-06-26 05:09:46
你应该使用
[ ! -e $dir ] && mkdir $dir单个"[“是调用test的快捷方式,因此适用test语法。双"[[“改为使用bash的逻辑语法,这是完全不同的。
由于您希望在测试返回true时执行命令,因此应使用"&&“-- "||”语法仅在测试返回false时运行命令。
编辑:
查看bash手册页可以发现,条件表达式(使用[[)得到的表达式也理解-e语法。那一节没有提到"!“用于否定结果,尽管它在命令行上尝试时有效。我的猜测是,您的系统运行的bash版本可能与评论者的版本不同,不理解"!“?测试的手册页清楚地指出"!“是受支持的,所以在进一步探索之前,我会先试一试,看看它是否有效。
发布于 2012-06-26 05:11:31
语法工作
至少,它对我来说是有效的。例如:
# Inverted logic. Returns false because directory exists.
$ [[ ! -e /tmp ]]; echo $?
1您确定您正在使用Bash吗?检查您的shell和版本。
$ echo $SHELL $BASH_VERSION
/bin/bash 4.2.10(1)-release更好的方法
你的条件逻辑有点复杂。对于你想要做的事情,这是一个清晰得多的语法:
dir=/tmp/foo
[[ -e "$dir" ]] || mkdir "$dir"这在语义上更加清晰,并且表达了没有倒置逻辑的意图。在某些情况下,您可能需要反向测试,但您的示例不是其中之一。
https://stackoverflow.com/questions/11197369
复制相似问题