Bash syntax behaviour : [[ vs [

Hello.

In the following :
RESTORE_FF contain a file name : a_file.tar.gz
I am testing in a directory if "a_file.tar.gz" exists and or if any file like "a_file.tar.gz" exists.
So "a_file.tar.gz" will give me file exists
So "a_file.tar.gz." will give me file exists
So "a_file.tar.gz.2013_12_25" will give me file exists

Now my question :
In the search directory there is a file : a_file.tar.gz.
Why

if [[ -f $RESTORE_FF.* ]] ; then echo "Multiple files exists" ; fi

print nothing
and why

if [[  !  -f  $RESTORE_FF.* ]] ; then echo "Multiple files exists" ; fi

print :

Multiple files exists

and why

if [ -f $RESTORE_FF.* ] ; then echo "Multiple files exists" ; fi

print :

Multiple files exists

Any help is welcome

$ cat test
#!/bin/bash

# Create file and compress for testing..
touch test
tar -zcvf a_file.tar.gz test 

# List file
ls *.gz 

# Variable declaration
RESTORE_FF="a_file.tar.gz"

# -f : Return true value if file exists and regular file

# Double bracket, if file exist print message
if [[ -f $RESTORE_FF.* ]] ; then echo "Multiple files exists" ; fi

# Double bracket with not operator, if file not exist print message
if [[  !  -f  $RESTORE_FF.* ]] ; then echo "Multiple files exists" ; fi

# Single bracket, if file exist print message
if [ -f $RESTORE_FF.* ] ; then echo "Multiple files exists" ; fi
$ bash test 
test
a_file.tar.gz
Multiple files exists

$ sh test 
test
a_file.tar.gz
test: 16: test: [[: not found
test: 19: test: [[: not found

if you want to check multiple files, with wildcard you can use ls or find something like this

if ls  path/to/files*  &> /dev/null; then
    echo "files exist"
fi

Perhaps this may be enough:

exists() {
  [ -e "$1" ]
}
if exists "$RESTORE_FF"*; then
  echo "At least one file exists"
fi

If you need to specifically test for a regular file, you could try something like

exists_file() {
  for _f do
    [ -f "$_f" ] && return
  done
  return 1
}

I thank every body for their solutions, but my question was about the syntax and why I got these three behavior :

In the search directory there is a file : a_file.tar.gz.
Why

if [[ -f $RESTORE_FF.* ]] ; then echo "Multiple files exists" ; fi

print nothing
and why

if [[  !  -f  $RESTORE_FF.* ]] ; then echo "Multiple files exists" ; fi

print :

Multiple files exists

and why

if [ -f $RESTORE_FF.* ] ; then echo "Multiple files exists" ; fi

print :

Multiple files exists

In the case of single brackets, pathname expansion does get performed, however in the case of double brackets this is not the case, so in your example with single brackets after variable expansion of $RESTORE_FF.* to a_file.tar.gz.* , the pathname pattern gets expanded to a_file.tar.gz. , so it would look for the literal file a_file.tar.gz. and in the case of double brackets for the literal file a_file.tar.gz.* , which does not exist. The example with single brackets will give a syntax error if more than one file with the given pattern exists.

1 Like

Thank you very much.