5

I have the following lines of bash script to test whether a file exists:

MYAPPPATH=$(find $APPDIR -iname myapp* -print)
if [ -e $MYAPPPATH ]
then
    echo "File exists" 
fi

However when file starting with "myapp" does not exist, therefore MYAPPPATH='', the above check succeeds again. See what happens when using set -x and the file does not exist:

++ find /path/to/app -iname 'myapp*' -print
+ MYAPPPATH=
+ '[' -e ']'
+ echo 'File exists'

What is the reason for this?

What do I need to do in order to make this work as expected?

12

When your variable is empty, your command becomes:

[ -e ]

In this case, you call [..] with one argument -e. String "-e" is not null, so test return true.

This behavior is defined by POSIX test:

In the following list, $1, $2, $3, and $4 represent the arguments presented to test:

0 arguments:

Exit false (1).

1 argument:

Exit true (0) if $1 is not null; otherwise, exit false.

....

To make it works, you must double quote your variable:

[ -e "$MYAPPPATH" ]

This works because -e with an argument that is an empty string is false.

5

Get used to quoting variables. Always quote them; that prevents misassessments when it is necessary:

if [ -e "$MYAPPPATH" ]

This would not have happened with the bash-specific compound command:

if [[ -e $MYAPPPATH ]]
  • 4
    Strictly speaking, [[...]] was copied by bash from ksh. It's also supported by zsh. So it's not bash-specific (though it's not standard/POSIX sh syntax so should not be used in sh scripts). – Stéphane Chazelas Nov 20 '14 at 11:34
2

There are some other ways:

  1. Check variable before (with editions according to comments)

    if [ -n "$MYAPPPATH" ] && [ -e "$MYAPPPATH" ] ; then ...
    
  2. Use locate* instead of find

    if locate -w "$APPDIR/myapp*" ; then ...
    

*1 To use locate don't forget to update files database by updatedb

  • -n "$MYAPPPATH" is easier to understand. – Hauke Laging Nov 20 '14 at 11:32
  • -a/-o should be avoided. Here, probably $MYAPPPATH starts with ./ or /, so it shouldn't be a problem, but that code above fails to work properly with some shells (like bash) with MYAPPPATH='!' or MYAPPPATH='(' or MYAPPPATH='-e'... use if [ -n "$MYAPPPATH" ] && [ -e "$MYAPPPATH" ]; then... – Stéphane Chazelas Nov 20 '14 at 11:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.