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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:48:12  来源:igfitidea点击:

bash if -a vs -e option

bash

提问by wheleph

Both about -aand -eoptions in Bash documentationis said:

Bash 文档中的about-a-eoptions都说:

-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/Resultsexists 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 -aand ! -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:

所以:

  1. What is a difference between -aand -eoptions?
  2. Why -aproduces a strange result when used inside single brackets?
  1. -a-e选项有什么区别?
  2. 为什么-a在单括号内使用时会产生奇怪的结果?

回答by Johannes Schaub - litb

I researched, and this is quite hairy:

我研究了一下,这很毛茸茸:

-ais deprecated, thus isn't listed in the manpage for /usr/bin/testanymore, but still in the one for bash. Use -e. For single '[', the bash builtin behaves the same as the testbash builtin, which behaves the same as /usr/bin/[and /usr/bin/test(the one is a symlink to the other). Note the effect of -adepends 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 内置函数的行为与testbash 内置函数相同,后者的行为与/usr/bin/[/usr/bin/test(一个是另一个的符号链接)。注意 的效果-a取决于它的位置:如果它在开头,则表示file exists。如果它在两个表达式的中间,则表示逻辑and

[ ! -a /path ] && echo existsdoesn't work, as the bash manual points out that -ais 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 andhere.

[ ! -a /path ] && echo exists不起作用,因为 bash 手册指出它在那里-a被认为是一个二元运算符,所以上面的不是解析为 anegate -a ..而是解析为 a if '!' and '/path' is true(非空)。因此,您的脚本总是输出"-a"(实际上是测试文件),而"! -a"这里实际上是二进制文件and

For [[, -aisn't used as a binary andanymore (&&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 autoconfsystem 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/[", ..."