Bash is incredibly flexible and offers various options for testing files. And if you’re looking for a way to test your files, the Bash file test operators will take you places.
In this tutorial, you’ll learn different file test operators and how to use them to test whether a file exists, is readable, is empty, and so on.
Read on and befriend the Bash file test operators!
Prerequisites
This tutorial will be a hands-on demonstration. If you’d like to follow along, be sure you have the following:
- A Linux system with Bash installed – This tutorial uses Ubuntu 20.04.
Most Linux distributions have Bash installed by default. But if you’re using Windows, you can install the Windows Subsystem for Linux (WSL) to get a Bash shell.
- A user account with sudo privileges to run commands as root – This tutorial uses a root account for simplicity. But using a non-root user with sudo access is always recommended.
- This tutorial assumes you have SSH access to your Linux system.
What Are Bash File Test Operators?
Before you get your hands dirty with the test operators, take a peek at how they work. File test operators let you test various aspects of a file like if a file exists, is readable/writable, etc.
Using file test operators can help to prevent errors in your Bash scripts. The code below is a boilerplate for the if statement. The if-else statement is a powerful tool you’ll often see in Bash scripts.
Remember that the then and else parts of the code block are optional. You can use an if statement without them.
# Represents the file that you want to test.
# Replace file_name with the target file's name to test.
FILE="file_name"
# Operator - The file test operator to use.
if [ Operator $FILE ]
then
# Tasks to perform if the Operator returns true.
do something
else
# Tasks to perform if the Operator returns false.
do something
fi
Checking if a File Exists
You’ve seen a glimpse of how the test operators work, but that’s not enough to better understand the ins and outs of using them. So start with a basic example, like checking if a file exists.
In the real world, you may want to check if a configuration file exists before creating one. You don’t want to waste time building a configuration file from the ground up just to find out the same one already exists.
To check if a file already exists:
1. Open your terminal, and run the touch command below to create a new test.txt file. This command doesn’t provide output, but you’ll verify the file in the next step.
touch test.txt
2. Next, run the following ls command to list the newly-created file (test.txt) in your working directory.
ls -al test.txt
The output below verifies that you’ve successfully created the test.txt file.
Now that you have a test file, you can use the boilerplate code block in a Bash script to check if the file exists in the following steps.
3. Run the below command to create (touch), and open a new shell script file (if_file_exists.sh) in your preferred text editor (nano).
touch if_file_exists.sh && nano if_file_exists.sh
4. Now, populate the code below into your new if_file_exists.sh file, save the file and close the editor.
- Runs an if-else statement to test if a specified file exists.
- If the operator returns true, you’ll get a message saying the file exists.
- If the operator returns true, you’ll get a message saying the file doesn’t exist. But this time, the file is automatically created, taking the name you defined in the FILE variable.
The #!/bin/bash line at the top of the file is known as a shebang. A shebang tells your system which interpreter to use to run the script, in this case, Bash. If you don’t include a shebang, your system uses the default interpreter, which might not be Bash. The shebang’s absence can cause your script to fail.
#!/bin/bash
# FILE - A variable that holds the value of the file you want to test.
# You can reuse this same code block to test different files
# by changing the value of the $FILE variable.
FILE="test.txt"
# The -e operator tests for file existence
if [ -e $FILE ]
then
# If the operator returns true, print a message saying the file exists.
echo "$FILE exists"
else
# If the operator returns true, print a message saying the file doesn't exist,
# then creates the file with the name you defined in the FILE variable.
echo "$FILE does not exist, creating new file" && touch test.txt
fi
5. Run the below command to execute your new script (if_file_exists.sh)
bash if_file_exists.sh
If all goes well, you’ll see the test.txt exists message printed to your terminal, as shown below.
6. Next, run the following commands to delete (rm -rf) the test file (test.txt), and list all files in your working directory.
rm -rf test.txt
ls test.txt
Below, you can verify the test.txt is no longer listed.
7. Rerun the command below to execute your if_file_exists.sh script.
Since the test.txt file doesn’t exist anymore, the script creates a new test.txt file when the -e operator returns false.
bash if_file_exists.sh
8. Finally, run the ls command below to list the test.txt file in your working directory.
ls -al test.txt
The output below confirms your script created a new test.txt file.
Checking if a File is a Regular or Special File
Before opening or processing a file, you may want to check first if that file is regular or special. Why? A special file is a type of file stored in a file system, so be cautious not to mess around with these files.
For example, a common error when opening a special file is the “No such file or directory” error. This error occurs when the file you’re trying to open doesn’t exist. But the same error can also occur when opening a special file instead of a regular one.
Open a new special_file.sh file in your text editor, add the following code and save the changes.
The code below is similar to the previous one. But this code uses the -f
operator instead of the -e
operator. The -f
operator tests if a specified file (/dev/vmmon
) is a regular file.
#!/bin/bash
# The /dev/vmmon file is a special file
# used for communicating with hardware devices in Linux.
FILE="/dev/vmmon"
# Test if the file
if [ -f $FILE ]
then
# If the operator returns true, you'll get a message saying
# the file is a regular file.
echo "$FILE is a regular file"
else
# If the operator returns true, you'll get a message saying
# the file either doesn't exist or is a regular file.
echo "Either $FILE does not exist or is not a regular file"
fi
Now, run the command below to execute your special_file.sh
script.
bash special_file.sh
Since the file (/dev/vmmon) specified in the FILE
variable is a special file, you’ll get the message below.
Checking if a Directory Exists
So far, you’ve learned how to check if a file exists. But does the same method applies to directories? Yes, by using the -d
test operator. This operator comes in handy if you plan to take action based on whether or not a directory exists.
Perhaps you want to copy all files from one directory to another. If the target directory doesn’t exist, you can create it before copying the files.
1. Run the ls command below to list the example-dir from the working directory.
ls -la example-dir
You’ll get a message saying No such file or directory since the directory doesn’t exist. If you don’t want your flow interrupted just because a directory doesn’t exist, jump to the next step.
2. Next, open a new file named if_dir_exists.sh in your text editor, add the code below and save the file. The following code tests if a specified directory exists and performs tasks depending on what value the -d operator returns.
You can achieve the same result by switching the if and else statements around using the negate operator (!). In real-world situations, the ! operator can help write a cleaner and more concise script.
#!/bin/bash
# Define the directory name in the dir variable
dir=example_dir
# Test if the directory (dir) exists
if [ ! -d $dir ]
then
# If the operator returns true, create a directory against the dir variable's value
mkdir $dir
# Copy the test.txt file to the newly-created directory
cp test.txt $dir
# Prints a message about the tasks performed above.
echo "The directory has been created, and the test.txt file has been copied."
else
# If the operator returns false,
# the echo command prints a message saying the directory exists.
echo "Directory $dir exists"
fi
3. Now, run the command below to execute your script (if_dir_exists.sh)
bash if_dir_exists.sh
You can see the message saying The directory has been created, and the test.txt file has been copied since the example_dir doesn’t exist.
4. Finally, run the ls command against the example_dir directory to confirm the directory exists and contains the test.txt file.
ls -la example_dir
Checking If a File is Empty
You already know how to use the three most used file test operators (-e
, -f
, and -d
) to up your scripting skills. But there are still other operators you’d love to look into.
Typically, instead of highlighting a file’s contents to copy to another file, you’d run a command to do the work for you. But hold your horses as your target file may not be empty.
Why not use the -s
operator to check if a file exists and is not empty? This operator returns true if the file exists and has a size greater than zero.
1. Open a new file named empty_file.sh in your text editor, add the following code, and save the file.
The following code tests if a specified file is empty and prints a message depending on what value the -s operator returns.
#!/bin/bash
# Defines the name of the target file
FILE=test.txt
# The -s operator tests if the target file exists and is not empty
if [ -s $FILE ]
then
# If the operator returns true, the echo command prints a message
# saying the file exists and is not empty.
echo "$FILE exists and is not empty"
else
# If the operator returns false, the echo command prints a message
# saying the file either does not exist or is empty.
echo "$FILE either does not exist or is empty"
# Add text to the target file
echo "This is a test. This is not an empty file" > $FILE
fi
2. Now, run the below command to execute your script (empty_file.sh).
bash empty_file.sh
Below, you can see the message saying that test.txt either does not exists or is empty. But simultaneously, the script adds text to the test.txt file.
3. Run the cat command below to verify the test.txt file contains the added text.
cat test.text
4. Finally, rerun the bash command below to execute the empty_file.sh script.
bash empty_file.sh
Below, you can see the output changed to test.txt exists and is not empty since the test.txt file now contains some text and has a size greater than zero (0).
Checking if a File Exists and is Readable
Perhaps your automation involves reading files to perform tasks. The success of those tasks will depend on whether the files are readable. Writing a script to check if a file exists and is readable will come in handy as a solution.
To demonstrate checking if a file exists and is readable:
1. Run the following command to log in to another user account (ata).
su - ata
Your prompt changes ($) to indicate that you are logged in as the other user.
Alternatively, you can change the file’s permission to readable, writable, or both with the chmod command.
2. Once logged in, create a new file called readable_file.sh with your text editor
Add the following code to the readable_file.sh file, and save the changes. This code checks if a file called test.txt in the /root directory exists and is readable.
#!/bin/bash
# Define the target file
FILE=test.txt
# Test if the target file is readable.
# You can change -r to -w to test if a file is writeable instead.
if [ -r $FILE ]
then
# If the operator returns true, print a message saying
# the file exists and is readable.
echo "$FILE exists and is readable"
else
# If the operator returns false, print a message saying
# the file either does not exist or is unreadable.
echo "$FILE does not exist or is unreadable"
fi
3. Now, run the below command to execute the readable_file.sh script.
bash readable_file.sh
This time, you’ll see a message saying /root/test.txt does not exist or is not readable. Since the text.test file is located in the /root directory, the current user (ata) doesn’t have read permissions for the text.txt file.
4. Finally, run the below commands to perform the following:
- Change the sudoers file to let the current user (ata) use
sudo
to run elevated commands.
- Execute the readable_file.sh script, which tests if a specific file is readable.
sudo bash
bash readable_file.sh
You can see below that the output prints test.txt exists and is readable because the ata user now has read permission to the test.txt file.
Conclusion
A testing phase is always a priority before making drastic changes, whether on files or directories on your system. And in this tutorial, you’ve learned about the Bash file test operators and how to use them to test if a file (regular or special) or directory exists or if a file is readable or not.
With these newfound skills, you can confidently decide which action to take based on the result of the tests. But there are many other ways you can use Bash file test operators.
Why not try to check a file’s extension? Or perhaps check if multiple files exist to see if all the files you need are available?