首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我在Bash条件中使用not运算符得到"command NOT found“?

为什么我在Bash条件中使用not运算符得到"command NOT found“?
EN

Stack Overflow用户
提问于 2012-06-26 05:06:10
回答 3查看 7.9K关注 0票数 1

如果我有

代码语言:javascript
复制
if [ ! -e $dir ];
then
 mkdir $dir
fi 

工作,但不是

代码语言:javascript
复制
[[ ! -e $dir ]] || mkdir $dir 

为什么?

编辑0

使用[[ ...,我得到了

代码语言:javascript
复制
 line 34: [[ !: command not found

编辑1

代码语言:javascript
复制
bash --version
GNU bash, version 3.2.25(1)-release (i686-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

编辑2

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

代码语言:javascript
复制
[user@host ~]$ [ -e /tmp ] && date
-bash: [: missing `]'
[user@host ~]$ [ -e /tmp ] && date
mar jun 26 10:05:50 CLT 2012
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-01 01:59:50

特别是在编辑2之后,在我看来,这真的是一个“有趣”字符的问题,要么是非打印字符混合在一起,要么是看起来正常但奇怪的字符,比如不间断的空格。这些可能很难检测到;在编辑器中可能看起来完全正常,即使您使用cat -v之类的东西查看脚本,它也不会总是清晰地显示有趣的字符。如果您的系统上有xxd,这是一种非常好的方式来精确查看文件中的内容。下面是这类问题的快速演示:

代码语言:javascript
复制
$ 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 (以及morevi等)时,该脚本看起来完全正常,但前两个命令失败。xxd说明了原因:第一个命令在[-e之间有一个UTF-8不间断空格(在十六进制清单中显示为c2a0,在文本清单中显示为[..-e ),第二个命令在/tmp]之间有一个不间断空格(在文本清单中显示为/tmp..])。

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

票数 1
EN

Stack Overflow用户

发布于 2012-06-26 05:09:46

你应该使用

代码语言:javascript
复制
[ ! -e $dir ] && mkdir $dir

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

由于您希望在测试返回true时执行命令,因此应使用"&&“-- "||”语法仅在测试返回false时运行命令。

编辑:

查看bash手册页可以发现,条件表达式(使用[[)得到的表达式也理解-e语法。那一节没有提到"!“用于否定结果,尽管它在命令行上尝试时有效。我的猜测是,您的系统运行的bash版本可能与评论者的版本不同,不理解"!“?测试的手册页清楚地指出"!“是受支持的,所以在进一步探索之前,我会先试一试,看看它是否有效。

票数 3
EN

Stack Overflow用户

发布于 2012-06-26 05:11:31

语法工作

至少,它对我来说是有效的。例如:

代码语言:javascript
复制
# Inverted logic. Returns false because directory exists.
$ [[ ! -e /tmp ]]; echo $?
1

您确定您正在使用Bash吗?检查您的shell和版本。

代码语言:javascript
复制
$ echo $SHELL $BASH_VERSION
/bin/bash 4.2.10(1)-release

更好的方法

你的条件逻辑有点复杂。对于你想要做的事情,这是一个清晰得多的语法:

代码语言:javascript
复制
dir=/tmp/foo
[[ -e "$dir" ]] || mkdir "$dir"

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11197369

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档