Files – How to Use stat or Bash to Check if FILENAME Refers to a File

filesstat

Does the stat command offer, or does bash offer, a straightforward way to check whether FILENAME refers to a file rather than, say, a directory?

Using bash and stat, here is my ugly solution:

if RESPONSE="$(LC_ALL=C stat -c%F FILENAME)"\
 && [ "$RESPONSE" = 'regular file'\
 -o "$RESPONSE" = 'regular empty file' ]
then
    # do something ...
fi

See also this related question.

Best Answer

The -f test will be true if the given name is the name of a regular file or a symbolic link to a regular file. The -h test will be true if the given name is the name of a symbolic link. This is documented in both man test (or man [), and in help test in a bash shell session. Both tests are standard tests that any POSIX test and [ utility would implement.

name=something

if [ -f "$name" ] && ! [ -h "$name" ]; then
    # "$name" refers to a regular file
fi

The same thing using stat on OpenBSD (the following bits of code also uses the standard -e test just to make sure the name exists in the filesystem before calling stat):

name=something

if [ -e "$name" ] && [ "$(stat -f %Hp "$name")" = "10" ]; then
    # "$name" refers to a regular file
fi

(a filetype of 10 indicates a regular file).

If using GNU stat:

name=something

if [ -e "$name" ] && [[ $(stat --printf=%F "$name") == "regular"*"file" ]]; then
    # "$name" refers to a regular file
fi

The pattern in this last test matches both the string regular file and regular empty file.

Related Question