bash if -a vs -e选项

时间:2008-11-26 16:38:04

标签: bash

Bash documentation中的-a-e两个选项都说:

-a file
    True if file exists.
-e file
    True if file exists. 

试图找出差异,我运行了以下脚本:

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存在并且是一个目录。这就是我得到的:

-e
-a
! -a

这似乎有点奇怪(注意-a! -a)。但是当我在类似的脚本中使用双括号(例如if [[ -e ${resin_dir} ]])时,它会提供合理的输出:

-e
-a

所以:

  1. -a-e选项之间有什么区别?
  2. 为什么-a在单括号内使用会产生奇怪的结果?

3 个答案:

答案 0 :(得分:64)

我研究过,这很毛茸茸:

-a已弃用,因此不再列在/usr/bin/test的联机帮助页中,但仍在bash中。使用-e。对于单个'[',bash内置行为与test bash内置行为相同,其行为与/usr/bin/[/usr/bin/test相同(一个是另一个的符号链接)。请注意-a的效果取决于其位置:如果它位于开头,则表示file exists。如果它位于两个表达式的中间,则表示逻辑and

[ ! -a /path ] && echo exists不起作用,因为bash手册指出-a在那里被认为是二元运算符,因此上述内容不会被解析为negate -a ..而是作为if '!' and '/path' is true(非空)。因此,您的脚本始终输出"-a"(实际上测试文件),"! -a"实际上是二进制文件and

对于[[-a不再用作二进制and(在那里使用&&),因此其唯一的目的是检查那里的文件(虽然被弃用)。所以,否定实际上就是你所期望的。

答案 1 :(得分:3)

测试运算符的“-a”选项有一个含义是一元运算符,另一个含义为二元运算符。作为二元运算符,它是'和'连词(而'-o'是'或'连词)。作为一元运算符,它显然测试文件的存在。

autoconf系统建议您避免使用“-a”,因为它会导致混淆;现在我明白了为什么。实际上,在便携式shell编程中,最好将条件与“&&”或“||”结合起来。

我认为@litb走在正确的轨道上。当你有'! -a ${resin_dir}'时,Bash可能会将其解释为“是字符串'!'非空,并且'$ {resin_dir}'中的字符串非空,答案是肯定的.Korn shell对此有不同的看法,而Bourne shell则是另一个视图 - 所以远离'{{ 1}}”。

在Solaris 10上:

-a

答案 2 :(得分:0)

双括号[[exp]]是一个内置的bash。在bash -a和-e中是相同的,可能是为了一些向后兼容性。

单括号[exp]是外部命令“test”的别名。在“test”中,-a是逻辑AND。虽然[没有AND $ STRING]看起来应该是假的,但测试有一些语法怪癖,这就是为什么我建议使用bash builtin [[exp]],这往往更加理智。

注意: bash确实调用/ bin / [当你使用“[”。

$ [ $UNASIGNED_VAR == "bar" ]
bash: [: ==: unary operator expected

错误显示bash调用[。 strace还显示“execve(”/ usr / bin / [“,...”