Finding if one or more files exist in a directory using bash.

A common problem I’ve come across in bash is that there doesn’t seem to be a way to check for the existence of multiple files in a directory. If you wanted to find out whither a particular file exists you could do the following:

#!/bin/bash
if [ -e ~/files/x.txt ];then
echo "Found file"
else
echo "Did not find file"
fi
me@pc:~$ if [ -e ~/files/x.txt ];then echo "Found file";else echo "Did not find file";fi
Did not find file
me@pc:~$ echo hello > files/x.txt
me@pc:~$ if [ -e ~/files/x.txt ];then echo "Found file";else echo "Did not find file";fi
Found file
me@pc:~$

See http://www.faqs.org/docs/bashman/bashref_68.html

No problem there. OK now let’s try and do that using a wild card

#!/bin/bash
if [ -e ~/files/* ];then
echo "Found file"
else
echo "Did not find file"
fi
me@pc:~$ rm files/*
me@pc:~$ if [ -e ~/files/* ];then echo "Found file";else echo "Did not find file";fi
Did not find file
me@pc:~$ echo hello > files/x.txt
me@pc:~$ if [ -e ~/files/* ];then echo "Found file";else echo "Did not find file";fi
Found file
me@pc:~$

Everything looks fine *until* there is more than one file that meets the test criteria.

me@pc:~$ echo hello > files/y.txt
me@pc:~$ if [ -e ~/files/* ];then echo "Found file";else echo "Did not find file";fi
bash: [: /home/me/files/x.txt: binary operator expected
Did not find file
me@pc:~$

So what’s happening ? Well bash is expecting only one item in the search criteria so it bombs out. How I got around this was to run a ls command using the same glob and ignore the output by redirecting both the standard output and standard error to /dev/null

ls -1 ~/files/* > /dev/null 2>&1
if [ "$?" = "0" ]; then
echo "Found file"
else
echo "Did not find file"
fi

So let’s try it.

me@pc:~$ rm files/*
me@pc:~$ ls -1 ~/files/* > /dev/null 2>&1; if [ "$?" = "0" ]; then echo "Found file"; else echo "Did not find file";fi
Did not find file
me@pc:~$ echo hello > files/x.txt
me@pc:~$ ls -1 ~/files/* > /dev/null 2>&1; if [ "$?" = "0" ]; then echo "Found file"; else echo "Did not find file";fi
Found file
me@pc:~$ echo hello > files/y.txt
me@pc:~$ ls -1 ~/files/* > /dev/null 2>&1; if [ "$?" = "0" ]; then echo "Found file"; else echo "Did not find file";fi
Found file
me@pc:~$

EDIT: Unescaped the html

Tags:

7 Responses to “Finding if one or more files exist in a directory using bash.”

  1. Mike says:

    Thanks – just the thing

  2. elara says:

    Thanks, just what I was looking for.
    Tricky thing, the wildcard check

  3. paul says:

    doe not work if there are *many* files matching…
    if ls gives an ‘Argument list too long’, this behaves like there were no matches

  4. Joe says:

    You need to unescape your html entities!

  5. Barton says:

    paul… if you have that many files in a directory, you probably need to use find and xargs.

    The problem that I’m having is that I only want to find files in the current directory, and I don’t want the ‘ls’ to return true if a sub-directory exists. I’m thinking that my best bet is to use find in this case as well:

    if [ $(find . -maxdepth 1 -type f | wc -l) == "0" ]
    then echo “no files”
    else echo “files exist”
    fi

  6. RMT says:

    function exists {
    for x in $*; do
    test -e “$x” && return 0;
    done
    return 1
    }
    # THEN #
    if exists foo*; then echo foostar exists; fi

Leave a Reply