Check if a file exists with Bash

In your Bash script you’ll have to deal with files at some point. So knowing for sure whether a file exists or not comes in handy at some point. You can test for these conditions in an if statement luckily.

Normally, in Bash, the preferred way to test this condition is by using double square brackets([[ … ]]), which is the improved version of the single square brackets ([ … ]). Do keep in mind however that the double square brackets might not be available in other shells. So for portability you might want to prefer single square brackets over the double ones.

To test for the existence of a file we can use the -f file test operator. The -f operator returns true if the file for the specified path exists and is a actual file, so not a directory.

In the script below an example is shown, in which a file is created first and secondly the existence is validated.

#!/bin/bash

# 1. We create a file
touch ~/dirty_secrets.txt

# 2. Check whether the file exist
if [[ -f "$HOME/dirty_secrets.txt" ]]; then
  echo "You have dirty secrets"
fi

And now run the script.

$ ./dirty-secrets
You have dirty secrets

There are a couple things that the -f operator does and doesn’t take into account. It does check if the specified file is actually a file. So if the specified path is an existing directory it still returns false. It doesn’t check whether the file is a symlink or not. So if the specified path is a path to a symlink, it does return true.

Test if a file doesn’t exist

For checking if a file is not existing we can do something similar. In order to check whether a file doesn’t exist we negate the condition with an exclamation mark.

#!/bin/bash

# 1. Now we remove the file
rm ~/dirty_secrets.txt

# 2. And check whether the file exist
if [[ ! -f "$HOME/dirty_secrets.txt" ]]; then
  echo "Good boy, no dirty secrets"
fi

Lets see the result of the updated version of the script now.

$ ./dirty-secrets
Good boy, no dirty secrets

Create file if it doesn’t exist

A more likely use-case is that you want to create a file if it doesn’t exist yet. With a small modification we can do just that.

We can create the file by using the touch command.

#!/bin/bash

# 1. Store the files path in a variable
file="$HOME/dirty_secrets.txt"

# 2. Create a file if it doesn't exist
if [[ ! -f $file ]]; then
  touch $file
  echo "Created file '$file'"
fi

Lets see what happens when we run this version of the script.

$ ./dirty-secrets
Created file '/home/koen/dirty_secrets.txt'

Test if a folder exist

Testing for the existence of a directory is the same but uses a different operator. Where we used -f to check for the existence of a file, we use -d for directories.

#!/bin/bash

# 1. We create a file
mkdir ~/dirty_secrets

# 2. Check whether the directory exist
if [[ -d "$HOME/dirty_secrets" ]]; then
  echo "You have dirty secrets"
fi

When we run the script we get the following output.

$ ./dirty-secrets
You have dirty secrets

Check multiple files at once

Checking for multiple files at once can be done as well. In order to do so you combine the conditions with &&.

if [[ -f "$HOME/dirty_secrets/mine.txt" ]] && [[ -f "$HOME/dirty_secrets/ours.txt" ]]; then
  echo "You have dirty secrets"
fi

File test operators

In the above examples we used only the -f and -d operators. But there are a couple other useful operators for dealing with files. They are summed up in the table below.

OperatorReturns true when
-ffile exists and is a regular file
-dfile exists and is a directory
-efile exists
-sfile is not zero size
-Lfile is a symbolic link
-Sfile is a socket
-xfile has execute permissions

Learning more

The best way to learn more is to use Bash. A lot. Don’t forget that Google is your friend.

In case you learn well from books I would recommend these.

See Also

6 Non-Programming Books for Programmers