Checking if a File or Directory Exists in a Bash Script

One common thing I find myself needing to do in Linux bash shell scripting is to check if a file or directory exists. The opposite is equally important – to see if a file does not exist. This can be used to check if a previous install or config has been done or not, or to check for certain conditions.

This is done using the Linux “test” command and is generally done in conjunction with a simple “if fi” statement with some action taken as a result. There are several file operators that can be used with test, but the most common are -f for standard files and -d for directories. There is also -e that will check for any type, including non-standard files (think devices listed in /dev for example) as well as directories. You can find a full list of file operators on the test man page.

It is important to understand that the test command will not output anything to stdout – it relies on exit codes to report a success or failure. For the purposes of file and directory checks, an exit code of 0 is “success” and 1 if “failure”. To see the exit code of the last command run, you can use echo $?.

Check if a file /opt/guest-cust/readme.md exists:

test -f /opt/guest-cust/readme.md
echo $?
0

Because an exit code of 0 was returned, we know that the file exists.

Although you can use “test” this is usually simplified in bash scripting by using an expression within square brackets. I.e. test -f /opt/guest-cust/readme.md becomes [ -f /opt/guest-cust/readme.md ]

Here are some examples:

The below checks if a file with the full path /opt/guest-cust/cust_finished exists. If it does, it displays a string of text:

if [ -f /opt/guest-cust/cust_finished ]; then
    echo "Guest customization file exists!”
fi

You can also combine this with an else statement to report if the file does not exist:

if [ -f /opt/guest-cust/cust_finished ]; then
    echo "Guest customization file exists!”
else
    echo “Guest customization file is missing!”
fi

Alternatively, you can use a ! before the -f <filename> option to reverse the check. Rather than checking if the file exists, it will tell you if it doesn’t:

if [ ! -f /opt/guest-cust/cust_finished ]; then
    echo "Guest customization file is missing!”
fi

Directories work very similarly but use -d instead of -f. In this case we’re just checking if the /opt/guest-cust directory exists:

if [ ! -d /opt/guest-cust ]; then
    echo "Guest customization directory is missing!”
fi

You can also combine multiple conditions using && to check if multiple files exist. In this example, I’m looking for two files. If both files are missing, it prompts the user to reboot their system:

if [ ! -f /opt/guest-cust/system_rebooted ] && [ -f /opt/guest-cust/tcp_tuning ]; then
    echo "A system reboot is required for the TCP tuning parameter changes to take effect."
    read -p "Reboot now? (y/n):" -n 1 -r
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        shutdown -r now
    fi
fi

If for some reason you want to see if a non-standard file exists, you can use -e. An example would be to see if a SCSI device “sdc” exists in /dev:

if [ ! -e /dev/sdc ]; then
    echo "SCSI device sdc does not exist”
fi

I hope you found this helpful. I have been doing a lot of bash scripting lately for a number of automation tasks and will try to share more in future posts.

Leave a comment