Reputation: 13702
I wish to perform an action if a file does not exists in bash with the following command:
if [ ! -a $HOME/.some_directory ] ; then
# do something
fi
However the #do something
part is always executed regardless of the existence of $HOME/.some_directory
.
I've created a small test where I have tried all cases:
Here is a screenshot of the result:
Notes:
~/bin
is present while ~/bina
is not4.3.18
$HOME
instead of ~
because of this SO questionUpvotes: 1
Views: 1415
Reputation: 9926
-a
as a test if a file exists, is a unary expression ( one-sided ) is a remnant of ksh86
(KornShell 86). It has become obsolete in more modern, derivative shells and has been replaced by -e
which is part of the POSIX standard, but in many shells it is still a synonym of -e
for backwards compatibility.
-a
can also be used a binary expression (two sided) and then it means an AND logical operator (which is also obsolescent). Here -a
is interpreted this way because there is a !
symbol in front of it and a string behind it. Both sides evaluate to true, so by using AND the outcome then becomes logically true.
Using -e
fixes this since it cannot be interpreted in another way.
Another way would have been to negate that outcome of the test command like so:
if ! [ -a $HOME/.some_directory ] ; then
or use parentheses for grouping:
if [ ! \( -a $HOME/.some_directory \) ] ; then
But at any rate it is better to stick with operands that are not deprecated / obsolescent..
Upvotes: 3
Reputation: 123490
This behavior is specified in POSIX:
3 arguments:
- If $2 is a binary primary, perform the binary test of $1 and $3.
In your case, $2
is a -a
which is a binary primary operator, so $1
and $3
are treated as binary tests. Single words are tested as if with -n
("is non-empty string").
This means that your test is equivalent to:
[[ -n "!" && -n "$HOME/.some_directory" ]]
Upvotes: 2
Reputation: 5422
What happens if you try -d
instead of -a
?
[ -d FILE ] True if FILE exists and is a directory.
~ http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
Also, seems like -a
is deprecated - please review this StackOverflow thread for details.
Upvotes: 2
Reputation: 265
You put a wrong operator; "-a" means AND.
You need "-e" to check if a file exists.
Upvotes: 1