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?

3 Answers 3

13

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 ]]
1
  • 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). Commented Nov 20, 2014 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

2
  • -n "$MYAPPPATH" is easier to understand. Commented Nov 20, 2014 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... Commented Nov 20, 2014 at 11:33

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.