bash if-a vs-e选项
中的关于bash if-a vs-e选项,bash,Bash,中的关于-a和-e选项均表示: 为了找出区别,我运行了以下脚本: 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} ] ;
-a
和-e
选项均表示:
为了找出区别,我运行了以下脚本:
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\u wheleph/Results
存在并且是一个目录。这就是我得到的:
-e
-a
! -a
这似乎有点奇怪(注意-a
和!-a
)。但是,当我在类似的脚本中使用双括号(例如,if[[-e${resin\u dir}]]
)时,它给出了合理的输出:
-e
-a
因此:
-a
和-e
选项之间有什么区别-a
在单括号内使用时会产生奇怪的结果我研究过了,这很毛茸茸的:
-a
已弃用,因此不再列在/usr/bin/test
的手册页中,但仍然列在bash的手册页中。使用-e
。对于单个“[”,bash内置函数的行为与test
bash内置函数相同,后者的行为与/usr/bin/[/code>和/usr/bin/test
相同(一个是另一个的符号链接)注意<代码> -<代码>的位置取决于它的位置:如果它在开始,它意味着<代码>文件存在。如果它位于两个表达式的中间,则意味着逻辑<代码>和<代码> >
[!-a/path]&&echo exists
不起作用,因为bash手册指出,-a
在那里被认为是一个二进制运算符,因此上面的内容不是解析为否定-a..
而是解析为如果'!'和'/path'为true
(非空)。因此,脚本总是输出“-a”
(实际上是测试文件)和“!-a”
,实际上是二进制的和
对于[[
,-a
不再用作二进制,
(&&
),因此它的唯一用途是检查那里的文件(尽管已弃用)。因此,否定实际上实现了您所期望的功能。双括号[[exp]]是bash内置的。在bash中-a和-e是相同的,可能是为了向后兼容
单括号[exp]是外部命令“test”的别名。在“test”中,-a是一个逻辑AND。虽然[nothing AND$STRING]看起来应该是false,但test有一些语法上的缺陷,这就是为什么我建议使用bash内置的[[exp]],这往往更合理
注:
当您使用“[”时,bash确实会调用/bin/[
错误显示bash调用[。strace还显示“execve”(/usr/bin/[”,“…”测试运算符的“-a
”选项有一个作为一元运算符的含义,另一个作为二元运算符的含义。作为二元运算符,它是“and”连接符(而“-o
”是“or”连接符).作为一元运算符,它显然测试文件是否存在
autoconf
系统建议您避免使用“-a
”,因为它会引起混淆;现在我明白了原因。事实上,在便携式shell编程中,最好将这些条件与“&&
”或“|
”结合使用
我认为@litb的思路是正确的。当您有“!-a${resin\u dir}
”时,Bash可能会将其解释为“is the string”!”非空且是“${resin\u dir}”中的字符串“非空,答案是肯定的。Korn shell对此有不同的看法,而Bourne shell则有另一种看法-因此请远离”-a
”
在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
$
bash内置函数在一元模式下使用-a as-e,在二进制模式下使用-a as和。使用[[]]调用bash内置函数,这就是为什么您可以使用它获得合理的输出。如前所述,单括号调用接受一元但不正确处理它的测试二进制文件(应作为二进制文件使用)。实际上很少有shell调用/bin/test(或/bin/[)当你写“如果[…]”的时候。很久以前-是的;现在,不是。甚至香草Bourne shell都不是。是的,我认为shell内置代码总是优先考虑“[”对于bash来说根本不是内置代码。请看我在回答中的注释错误:[js@HOST2cpp]$help[[:[arg…]这是“测试”的同义词“内置,但最后一个参数必须是文字<代码>]',以匹配开头<代码>['[js@HOST2cpp]$alias foo bash:别名:foo:未找到[js@HOST2cpp]$这是否意味着alias现在是一个extern命令?不,它仍然是一个内置命令:)该死,好的:)。但是,删除bash脚本会显示“execve(“/usr/bin/[“,…有趣的是:在Solaris上,使用我的答案中的'truss-obash.truss-bash…',然后使用'grep-n exec bash.truss'只显示第1行执行bash本身。所以这很奇怪。(在Solaris上也没有/usr/bin/[在Solaris上-有一个/usr/bin/test。)
$ [ $UNASIGNED_VAR == "bar" ]
bash: [: ==: unary operator expected
$ 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
$