[SOLVED] if [ ! -a foo ] does not do what it's expected to do?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
if [ ! -a foo ] does not do what it's expected to do?
Hi:
Code:
$ cat t1.sh
#!/bin/sh
set -e
set -x
if [ ! -a /mnt/cd0 ] ; then
mkdir /mnt/cd0
fi
$ ./t1.sh
+ '[' '!' -a /mnt/cd0 ']'
+ mkdir /mnt/cd0
mkdir: cannot create directory '/mnt/cd0': File exists
If I use -d instead of -a then it doesn't execute 'mkdir /mnt/cd0', as expected. But the bash man page says:
Code:
-a file
True if file exists.
/mnt/cd0 is a directory. But then it is a file! And then t1.sh should not have executed 'mkdir /mnt/cd0'. But it does. What am I missing here?
How do you explain this?
It seems bash has some very peculiar ideas about the nature of directories. The output from this script only makes sense in a particular universe:
Code:
#!/bin/bash
mkdir /tmp/tea
if [ -a /tmp/tea ]; then
echo You have tea.
fi
if [ ! -a /tmp/tea ]; then
echo You have no tea.
fi
rmdir /tmp/tea
As you said, the results are specific to the -a operator; the -d operator produces the expected result(s), and so does the -a operator if you put it inside double brackets ([[ / ]]).
However I also feel that for things like temporary mount points that it's best to create that as well as remove it so as to not leave temporary unused files lying around. Further, there is a test concern to consider which is if that directory does exist, then is it already a mount for some other reason, so as a result the script should consider making that determination, failing, or trying to use an alternate mount point so as to not cause undesired system problems.
I think is a quirk due to -a having 2 meanings for the test (aka "[") builtin:
Code:
$ help test
...
-a FILE True if file exists.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
STRING True if string is not empty.
-e FILE True if file exists.
[ ! -a /tmp/tea ] is true because "!" is "true" (it's a nonempty string), and "/tmp/tea" is "true" for the same reason. Note that -e means the same as unary -a, and doesn't have this problem. Also you can put the "!" outside of the test:
Not remembering what the logical negation operator was, I looked in the internet and saw it was used this way:
Code:
if [ ! -<some primary> <filename> ]
But
Code:
if ! [ -<unary primary> <filename> ]
should be preferred I think, because it makes it clear what the scope of '!' is. In the case of '-a' if forces bash to interpret it as a unary operator. Thanks for the feedback.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.