In Bash scripts is very common to check if a file or a directory exist.
How do you check if a file or a directory exists using Bash?
In Linux everything is a file. You can use the test command followed by the operator -f to test if a file exists and if it’s a regular file. In the same way the test command followed by the operator -d allows to test if a file exists and if it’s a directory. The test command can also be represented with single square brackets [ ] or double square brackets [[ ]].
Now that you know how to check if a file or directory exist in a Linux system using Bash, let’s have a look at some practical examples.
For instance, you might want to check:
- if a log file already exists and create it if it doesn’t…
- if a directory required for the correct execution of your script exists…
And these are just two of hundreds of scenarios for which you might want to verify this.
Check If a File Exists using Bash
To verify if a file exists on a Linux system you can use the test command, represented by square brackets, followed by the -f flag:
[ -f filename ]
The expression above is a boolean expression and it’s often used together with a Bash if else expression to take different actions depending on the result of the expression.
If the file exists and is a regular file the expression above is true, otherwise is false.
A boolean expression can only have two values: true or false. Boolean expressions are used in Bash (and in other programming languages) to execute different commands based on the value of a condition.
The following script is an example of how to check if the file /var/log/install.log exists:
#!/bin/bash
FILENAME="/var/log/install.log"
if [ -f "$FILENAME" ]
then
echo "$FILENAME exists"
fi
As you can see, first we set the variable FILENAME and then we verify if the file exists using the test expression we have explained before.
If the file exists and it’s a regular file we use the echo command to print “/var/log/install.log exists” as you can see below:
localhost$ ./file_exists.sh
/var/log/install.log exists
The advantage of using a variable for the filename is that you don’t have to repeat the filename in the three places where you need to use it in the script, you can just replace it with the value of the variable $FILENAME.
This also allows to customise our script in case we want to verify the existence of a difference file (e.g. by passing the value of FILENAME as a command line argument instead of hardcoding it in the script).
Note: When you use the expression [ -f filename ] make sure there is a space after the opening square bracket and before the closing square bracket.
What happens if we forget the space after the opening square bracket?
localhost$ ./file_exists.sh
./file_exists.sh: line 5: [-f: command not found
Here it is, “command not found” because the Bash interpreter cannot understand [-f without space after the opening square bracket, because there’s no such command in Linux.
Now, let’s see how to verify if a directory exists.
Check If The File is Not Empty
Sometimes, after verifying that a regular file exists, we might also want to check if that file is not empty.
To do that we can still use the test expression, but this time followed by the -s flag.
I will create two files in the current directory using the touch and echo commands. The first file (testfile1) is empty and the second file (testfile2) is not empty.
(localhost) $ touch testfile1
(localhost) $ echo "Test file" > testfile2
Let’s write a script called check_empty_files.sh, here is the code:
#!/bin/bash
if [ -s testfile1 ]; then
echo "testfile1 is not empty"
else
echo "testfile1 is empty"
fi
if [ -s testfile2 ]; then
echo "testfile2 is not empty"
else
echo "testfile2 is empty"
fi
So, as you can see I’m using the test operator with the -s flag. And this is the output of the script:
(localhost) $ ./check_empty_files.sh
testfile1 is empty
testfile2 is not empty
The script works as expected and detects which file is empty and which one is not empty.
This script contains some duplicate code that could be removed simply by passing the filename as script argument via the command line.
Do you know how?
Check If a Directory Exists using Bash
Likewise, to verify if a directory exists using Bash you can use a very similar test expression:
[ -d dirname ]
As explained for the expression to verify if a file exists, also in this case the expression below can be used together with an if else statement.
Now, let’s examine an example of script that checks if the directory /var/log/ exists:
#!/bin/bash
DIRNAME="/var/log/"
if [ -d "$DIRNAME" ]
then
echo "$DIRNAME exists"
fi
And here is the output of the script:
localhost$ ./dir_exists.sh
/var/log/ exists
The rule about the space after the opening square bracket and before the closing square bracket also applies in this case.
As seen before, the variable DIRNAME allows to keep our script flexible in case we want to modify it to verify if a different directory exists.
Bash Nested Test Expressions
Now we want to combine the two test expressions in the same Bash script to check if a file or directory exist. How?
We can nest them based on the logic we want to implement in our script.
We will write a script called dir_file_exist.sh that:
- Checks if the directory test_dir exists in the current directory.
- Creates the directory if it doesn’t exist and prints “Directory test_dir created” in the shell.
- Verifies if the file test_file exists in the test_dir directory.
- Create the file if it doesn’t exist using the touch command.
Here is the script:
#!/bin/bash
DIRNAME="test_dir"
FILENAME="test_file"
if [ ! -d "$DIRNAME" ]
then
mkdir $DIRNAME
echo "Directory $DIRNAME created"
if [ ! -f "$FILENAME" ]
then
touch $DIRNAME/$FILENAME
echo "File $DIRNAME/$FILENAME created"
else
echo "File $DIRNAME/$FILENAME exists"
fi
else
echo "Directory $DIRNAME exists"
fi
The exclamation mark is used as negation of the -d and -f expressions.
We are verifying if the directory doesn’t exist and if the file doesn’t exist because we want to know if we have to create them.
So, it’s time to execute the script and see if it does what we expect:
Script Run #1
localhost$ ./dir_file_exist.sh
Directory test_dir created
File test_dir/test_file created
We can see that the directory test_dir and the file test_dir/test_file have been created because they didn’t exist:
localhost$ ls -al
total 8
drwxr-xr-x 4 testuser staff 128 19 Mar 01:43 .
drwxr-xr-x 10 testuser staff 320 19 Mar 01:43 ..
-rwxr-xr-x 1 testuser staff 341 19 Mar 01:43 dir_file_exist.sh
drwxr-xr-x 3 testuser staff 96 19 Mar 01:43 test_dir
localhost$ ls -al test_dir/
total 0
drwxr-xr-x 3 testuser staff 96 19 Mar 01:43 .
drwxr-xr-x 4 testuser staff 128 19 Mar 01:43 ..
-rw-r--r-- 1 testuser staff 0 19 Mar 01:43 test_file
Let’s execute the script again…
Script Run #2
localhost$ ./dir_file_exist.sh
Directory test_dir exists
This time the script simply executes the else branch for the test that checks if the directory test_dir doesn’t exist.
That’s why we see the message “Directory test_dir exists” and then the script ends its execution.
Other Bash Test Expressions
The test expressions we have seen are just two examples of what Linux provides.
The following table shows common test expressions you can use in your Bash scripts to make them more flexible and robust:
Test Expression | Meaning |
[ -f <file> ] | True if file exists and if it is a regular file |
[ -d <file> ] | True if file exists and if it is a directory |
[ -s <file> ] | True if file exists and its size is greater than zero |
[ -L <file> ] | True if file exists and if it is a symbolic link |
[ -p <file> ] | True if file is a name pipe (FIFO) |
[ -b <file> ] | True if file is a block special device |
You can also use the test expression to compare strings and integers. Something for another day!
Conclusion
In conclusion, this tutorial has showed you:
- Check if a file or directory exist using Bash.
- Use if else to take different actions depending on the value of the expression used to test if a file or directory exist.
- Write nested if else statements.
- Add the exclamation mark to the -f or -d test expressions to check if a file or directory doesn’t exist (the meaning of the exclamation mark in Bash is the negation of the expression that follows it).
Makes sense? 🙂
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design. He is a professional certified by the Linux Professional Institute.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for robotics with Raspberry Pi.