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?

trikelef
  • 411

3 Answers3

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.

cuonglm
  • 153,898
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 ]]
Hauke Laging
  • 90,279
  • 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

terdon
  • 242,166
Costas
  • 14,916
  • -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