10. Bash File Testing
Overview¶
Bash provides several conditional operators that can be used to check the characteristics and properties of files, directories, and special filesystem objects.
These tests are commonly used with if, while, and other conditional statements.
File Test Operators¶
| Operator | Description |
|---|---|
-b |
Checks if the file is a block special file |
-c |
Checks if the file is a character special file |
-d |
Checks if the path is a directory |
-e |
Checks if the path exists |
-f |
Checks if the path is a regular file |
-G |
Checks if the file is owned by the effective group ID |
-g |
Checks if the set-group-ID bit is set |
-k |
Checks if the sticky bit is set |
-L |
Checks if the path is a symbolic link |
-O |
Checks if the file is owned by the effective user ID |
-r |
Checks if the file is readable |
-S |
Checks if the file is a socket |
-s |
Checks if the file exists and has a non-zero size |
-u |
Checks if the set-user-ID bit is set |
-w |
Checks if the file is writable |
-x |
Checks if the file is executable |
Checking if a File Exists¶
The -e operator can be used to determine whether a file or path exists.
#!/bin/bash
file="./file"
if [ -e "$file" ]; then
echo "File exists"
else
echo "File does not exist"
fi
If the file does not exist:
Create the file:
Run the script again:
Here, -e returns true when the specified path exists.
Using quotes around variables such as "$file" is recommended because it prevents problems when the filename contains spaces or special characters.
Checking for a Regular File¶
The -f operator checks whether a path exists and is a regular file.
#!/bin/bash
file="./file"
if [ -f "$file" ]; then
echo "Regular file exists"
else
echo "Not a regular file"
fi
This is different from -e. For example, a directory can satisfy -e, but it will not satisfy -f.
Checking for a Directory¶
Use -d to determine whether a directory exists.
#!/bin/bash
directory="./backup"
if [ -d "$directory" ]; then
echo "Directory exists"
else
echo "Directory does not exist"
fi
Create the directory and test again:
Output:
Checking File Permissions¶
File tests can also be used to check permissions.
Readable¶
Writable¶
Executable¶
These tests are useful when a script needs to verify permissions before attempting an operation.
Checking File Size¶
The -s operator checks whether a file exists and has a size greater than zero.
#!/bin/bash
file="./data.txt"
if [ -s "$file" ]; then
echo "File contains data"
else
echo "File is empty or does not exist"
fi
This can be useful when a script needs to determine whether a generated file actually contains data.
Checking for a Symbolic Link¶
The -L operator checks whether a path is a symbolic link.
#!/bin/bash
file="./latest"
if [ -L "$file" ]; then
echo "Symbolic link"
else
echo "Not a symbolic link"
fi
For example:
The test will then identify latest as a symbolic link.
Waiting Until a File Exists¶
File tests can also be combined with a while loop.
The following script waits until myfile is created:
The ! operator negates the condition.
Without !:
means:
With !:
means:
Therefore, the loop continues while the file does not exist.
In another terminal, create the file:
The loop detects the file and exits:
The sleep 1 prevents the script from continuously checking the filesystem without a delay.
Combining File Tests¶
Multiple conditions can be combined to perform more specific checks.
#!/bin/bash
file="./script.sh"
if [ -f "$file" ] && [ -x "$file" ]; then
echo "Regular executable file"
else
echo "File is missing or not executable"
fi
Here:
checks that the path is a regular file, while:
checks that it is executable.
The && operator requires both conditions to be true.
Quick Examples¶
# Exists
[ -e "$file" ]
# Regular file
[ -f "$file" ]
# Directory
[ -d "$file" ]
# Readable
[ -r "$file" ]
# Writable
[ -w "$file" ]
# Executable
[ -x "$file" ]
# Non-empty
[ -s "$file" ]
# Symbolic link
[ -L "$file" ]
Key Concept¶
Bash file tests provide a simple way to make scripts aware of the filesystem. They can be used to verify that files or directories exist, check permissions, determine file types, and wait for files to appear.
A common pattern is:
while a negated test can be used for waiting:
These operators are fundamental when writing Bash scripts that interact with files, directories, logs, configuration files, temporary files, and other filesystem resources.