Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash if -a vs -e option

Tags:

bash

Both about -a and -e options in Bash documentation is said:

-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:

-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:

-e -a 

So:

  1. What is a difference between -a and -e options?
  2. Why -a produces a strange result when used inside single brackets?
like image 314
wheleph Avatar asked Nov 26 '08 16:11

wheleph


People also ask

What does [- Z $1 mean in bash?

$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script.

What is bash if [- N?

A null string in Bash can be declared by equalizing a variable to “”. Then we have an “if” statement followed by the “-n” flag, which returns true if a string is not null. We have used this flag to test our string “name,” which is null.

What is if option in bash?

Bash IF statement is used for conditional branching in the sequential flow of execution of statements.

What is if [- Z in bash?

In both cases, the -z flag is a parameter to the bash's "test" built-in (a built-in is a command that is built-into the shell, it is not an external command). The -z flag causes test to check whether a string is empty. Returns true if the string is empty, false if it contains something.


1 Answers

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 /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.

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.

like image 59
Johannes Schaub - litb Avatar answered Oct 04 '22 17:10

Johannes Schaub - litb