bash if -a vs -e 选项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/321348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
bash if -a vs -e option
提问by wheleph
Both about -a
and -e
options in Bash documentationis said:
Bash 文档中的about-a
和-e
options都说:
-a file
True if file exists.
-e file
True if file exists.
Trying to get what the difference is I ran the following script:
试图找出不同之处,我运行了以下脚本:
resin_dir=/Test/Resin_wheleph/Results
if [ -e ${resin_dir} ] ; then
echo "-e ";
fi
if [ ! -e ${resin_dir} ] ; then
echo "! -e";
fi
if [ -a ${resin_dir} ] ; then
echo "-a";
fi
if [ ! -a ${resin_dir} ] ; then
echo "! -a";
fi
/Test/Resin_wheleph/Results
exists and is a directory. And this is what I get:
/Test/Resin_wheleph/Results
存在并且是一个目录。这就是我得到的:
-e
-a
! -a
which seems to be a little strange (notice -a
and ! -a
). But when I use double brackets (e. g. if [[ -e ${resin_dir} ]]
) in the similar script it gives reasonable output:
这似乎有点奇怪(注意-a
和 ! -a
)。但是当我if [[ -e ${resin_dir} ]]
在类似的脚本中使用双括号(例如)时,它给出了合理的输出:
-e
-a
So:
所以:
- What is a difference between
-a
and-e
options? - Why
-a
produces a strange result when used inside single brackets?
-a
和-e
选项有什么区别?- 为什么
-a
在单括号内使用时会产生奇怪的结果?
回答by Johannes Schaub - litb
I researched, and this is quite hairy:
我研究了一下,这很毛茸茸:
-a
is deprecated, thus isn't listed in the manpage for /usr/bin/test
anymore, but still in the one for bash. Use -e
. For single '[', the bash builtin behaves the same as the test
bash builtin, which behaves the same as /usr/bin/[
and /usr/bin/test
(the one is a symlink to the other). Note the effect of -a
depends on its position: If it's at the start, it means file exists
. If it's in the middle of two expressions, it means logical and
.
-a
已弃用,因此不再在联机帮助页中列出/usr/bin/test
,但仍然在 bash的联机帮助页中。使用-e
. 对于单个 '[',bash 内置函数的行为与test
bash 内置函数相同,后者的行为与/usr/bin/[
和/usr/bin/test
(一个是另一个的符号链接)。注意 的效果-a
取决于它的位置:如果它在开头,则表示file exists
。如果它在两个表达式的中间,则表示逻辑and
。
[ ! -a /path ] && echo exists
doesn't work, as the bash manual points out that -a
is considered a binary operator there, and so the above isn't parsed as a negate -a ..
but as a if '!' and '/path' is true
(non-empty). Thus, your script always outputs "-a"
(which actually tests for files), and "! -a"
which actually is a binary and
here.
[ ! -a /path ] && echo exists
不起作用,因为 bash 手册指出它在那里-a
被认为是一个二元运算符,所以上面的不是解析为 anegate -a ..
而是解析为 a if '!' and '/path' is true
(非空)。因此,您的脚本总是输出"-a"
(实际上是测试文件),而"! -a"
这里实际上是二进制文件and
。
For [[
, -a
isn't used as a binary and
anymore (&&
is used there), so its unique purpose is to check for a file there (although being deprecated). So, negation actually does what you expect.
对于[[
,-a
不再用作二进制文件and
(&&
在那里使用),因此其唯一目的是检查那里的文件(尽管已弃用)。所以,否定实际上做了你所期望的。
回答by Jonathan Leffler
The '-a
' option to the test operator has one meaning as a unary operator and another as a binary operator. As a binary operator, it is the 'and' connective (and '-o
' is the 'or' connective). As a unary operator, it apparently tests for a file's existence.
-a
测试运算符的 ' ' 选项作为一元运算符具有一种含义,作为二元运算符具有另一种含义。作为二元运算符,它是“和”连接词(而“ -o
”是“或”连接词)。作为一元运算符,它显然是在测试文件是否存在。
The autoconf
system advises you to avoid using '-a
' because it causes confusion; now I see why. Indeed, in portable shell programming, it is best to combine the conditions with '&&
' or '||
'.
该autoconf
系统建议您避免使用“ -a
”,因为它会导致混乱; 现在我明白为什么了。的确,在可移植的shell 编程中,最好将条件与' &&
' 或' ||
'结合起来。
I think @litb is on the right track. When you have '! -a ${resin_dir}
', Bash may be interpreting it as "is the string '!' non-empty and is the string in '${resin_dir}' non-empty, to which the answer is yes. The Korn shell has a different view on this, and the Bourne shell yet another view - so stay away from '-a
'.
我认为@litb 走在正确的轨道上。当您有 ' ! -a ${resin_dir}
' 时,Bash 可能会将其解释为“是字符串 '!' 非空并且是 '${resin_dir}' 中的字符串非空,答案是肯定的。Korn shell 对此有不同的看法,而 Bourne shell 则是另一种看法 - 所以远离 ' -a
'。
On Solaris 10:
在 Solaris 10 上:
$ bash -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi'
Bad
$ ksh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi'
OK
$ sh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi'
sh: test: argument expected
$
回答by JimB
The double bracket [[ exp ]] is a bash builtin. In bash -a and -e are the same, probably for some backwards compatibility.
双括号 [[ exp ]] 是 bash 内置的。在 bash 中 -a 和 -e 是相同的,可能是为了向后兼容。
The single bracket [ exp ] is an alias for the external command "test". In "test", -a is a logical AND. Although [ nothing AND $STRING ] looks like it should be false, test has some syntax quirks, which is why I recommend using the bash builtin [[ exp ]], which tends to be more sane.
单括号 [ exp ] 是外部命令“test”的别名。在“test”中,-a 是逻辑与。尽管 [ nothing AND $STRING ] 看起来应该是假的,但 test 有一些语法怪癖,这就是我建议使用 bash 内置 [[ exp ]] 的原因,它往往更合理。
Note: bash really does call /bin/[ when you use "[".
注意:当您使用“[”时,bash 确实会调用 /bin/[。
$ [ $UNASIGNED_VAR == "bar" ]
bash: [: ==: unary operator expected
the error shows bash called [. An strace also shows "execve("/usr/bin/[", ..."
错误显示 bash 名为 [. strace 还显示“execve("/usr/bin/[", ..."