So, yesterday my boss had some unusual weirdness with a bash shell script that he was writing and together we were able to figure out what was going on. Here is a boiled down example of it.
He wanted to test that a file didn’t exist, and if so, perform some action. He wanted to use the ‘-a’ conditional test directive. Here is a little example.
if [ -a 'afile' ]; then echo "exists" ; else echo "not exists"; fi
when the file exists, it prints ‘exists’, and when it doesn’t exist, it prints ‘not exists’.
So far so good. Well, lets just switch things around a bit. He wanted the first condition to be the negative sense so we use the ! (bang) to not the results of ‘-a’.
if [ ! -a 'afile' ]; then echo "not exists"; else echo "exists"; fi
Well, this always prints ‘not exists’ regardless of the existence of the file. Now switch the operator to ‘-e’ (which is the operator that I use usually).
if [ ! -e 'afile' ]; then echo "not exists"; else echo "exists"; fi
Now things work as expected…
If you look up the man page for bash, you will see why my boss wanted to use ‘-a’, it is listed there as …
-a file
True if file exists.
And -e has an identical entry.
But, if you look up the man page for test, then you will see a different story.
EXPRESSION1 -a EXPRESSION2
both EXPRESSION1 and EXPRESSION2 are true
So, the question is, why is the ‘-a’ being processed by test instead of the shell? It is because in the if clause we are using ‘[' to initiate the test. '[' is actually the 'test' command (try running man [, or which [ ). Basically test was being asked if '!' is true and 'afile' is true, and they weren't.
So, use '-e' to eliminate that confusion, because '-e' means equal in both bash and test. Also, you could phrase it this way...
if ! [ -a 'afile' ]; then echo "not exists"; else echo "exists"; fi
i.e. put the bang outside of the test command.
There are many other ways that you could write this, but as you can see, for the sake of eliminating confusion, you should always prefer to use '-e' over '-a' when shell scripting.