When writing shell scripts in Bash, you might encounter situations that’ll require you to make decisions based on whether or not a particular file or directory exists.
In this article, we’re going over a few ways how you can check for existing files and/or directories in Bash.
What is the test command?
You can use theย testย command to find whether a file exists and, if it does, that kind of file you’re dealing with. There are three ways you can use theย testย command.
test Expression
[ expression ]
[[ expression ]]
If you want portability in your script, we suggest using the single bracket test command as available on all POSIX shells. The new, upgraded version of theย testย command ([[) is supported on most modern systems using Bash, Zsh, Ksh and of course, the default shell.ย
Also read: Bash โif elseโ statement examples
How to check existing files in Bash?
To check if a file exists, we’ll use theย testย command in conjunction and either the -e or -f flags. The -eย flag checks whether a file exists regardless of the file type, and theย -fย flag returns true only if the file in question is a regular file and not a directory or device.ย
We’ll also be using the if-else statement to make our code more readable. Any of the following three snippets will be able to check if a file called index.html in the /etc/lampp/index.html directory exists or not.
FILE=/etc/lampp/index.html
if test -f "$FILE"; then
echo "$FILE exists."
fi
FILE=/etc/lampp/index.html
if [ -f "$FILE" ]; then
echo "$FILE exists."
fi
FILE=/etc/lampp/index.html
if [[ -f "$FILE" ]]; then
echo "$FILE exists."
fi
If you want to perform different actions based on whether a file exists or not, throw in anย elseย statement in the aforementioned snippets.ย
FILE=/etc/lampp/index.html
if [ -f "$FILE" ]; then
echo "$FILE exists."
else
echo "$FILE does not exist."
fi
Always make sure to use double quotes when writing file names to avoid misparsing files with white spaces in them.
If you want, you can also use the test command without the if-else statements. Here’s how.
test -f /etc/lampp/index.html && echo "$FILE exists."
[ -f /etc/lampp/index.html ] && echo "$FILE exists."
[[ -f /etc/lampp/index.html ]] && echo "$FILE exists."
Note that in the above snippet, the command after theย &&ย logical operator will only execute if the test command’s exit status is true. If you’re looking to run a series of commands after theย &&ย operator, enclose the commands in curly brackets separated by either a semi-colon orย &&.
[ -f /etc/lampp/index.html ] && { echo "$FILE exist."; cp "$FILE" /tmp/; }
You can also perform an action based on the fact that a file isn’t present. Substitute theย &&ย operator or theย ||one. In this case, the command after theย || will only execute if the test command’s exit status is false.
[ -f /etc/lampp/index.html ] && echo "$FILE exist." || echo "$FILE does not exist."
Also read: How to compare Strings in Bash?
How to check existing directories in Bash?
Similar to files, you can also check for directories using the test command. All you have to do is add the -d flag.
FILE=/etc/lampp/
if [ -d "$FILE" ]; then
echo "$FILE is a directory."
fi
Or in a single line.
[ -d /etc/lampp ] && echo "$FILE is a directory."
Consider using double brackets instead of single ones if you’ll only be running your script on modern Linux distros.
Also read: How to exit Bash script?
How to check if a file doesn’t exist?
Like every other programming language, you can negate any test condition using the logical not (!) operator.ย
FILE=/etc/lampp/index.html
if [ ! -f "$FILE" ]; then
echo "$FILE does not exist."
fi
Or in a single line, as follows.
[ ! -f /etc/lampp/index.html ] && echo "$FILE does not exist."
Also read: Bash While loop explained
How to check multiple files at once in Bash?
You might think you’ll need to create a complex if-elseif-else statement tree to check for multiple files, but that’s not necessarily the case.
You can use theย -aย flag or the logical operator with the double bracketย testย command to check for multiple files at once.ย
if [ -f /etc/lampp/index.html -a -f /etc/lampp/index.php ]; then
echo "Both files exist."
fi
Or using && along with the double bracket test command.
if [[ -f /etc/lampp/index.html && -f /etc/lampp/index.php ]]; then
echo "Both files exist."
fi
Without theย ifย statements, the above snippets would look something like this, respectively.ย
[ -f /etc/lampp/index.html -a -f /etc/lampp/index.php ] && echo "Both files exist."
[[ -f /etc/lampp/index.html && -f /etc/lampp/index.php ]] && echo "Both files exist."
Also read: Bash functions explained
Common Bashย testย command flags
Theย testย command has many useful flags that you can use to filter down your search for files. The most common ones are as follows.ย
- -b FILE: Returns true if the FILE exists and is a special block file.
- -c FILE: Returns true if the FILE exists and is a special character file.
- -d FILE: Returns true if the FILE exists and is a directory.
- -e FILE: Returns true if the FILE exists and is a file regardless of type.
- -f FILE: Returns true if the FILE exists and is a regular file.
- -G FILE: Returns true if the FILE exists and has the same group as the user running the command.
- -g FILE: Returns true if the FILE exists and the set-group-id (sguid) flag is set.
- -k FILE: Returns true if the FILE exists and is set to a sticky bit flag.
- -L FILE: Returns true if the FILE exists and is a symbolic link (symlink).
- -O FILE: Returns true if the FILE exists and is owned by the user running the command.
- -p FILE: Returns true if the FILE exists and is a pipe.
- -r FILE: Returns true if the FILE exists and is a readable file.
- -S FILE: Returns true if the FILE exists and is a socket.
- -s FILE: Returns true if the FILE exists and has a non-zero file size.
- -u FILE: Returns true if the FILE exists and the set-user-id (suid) flag is set.
- -w FILE: Returns true if the FILE exists and is a writable file.
- -x FILE: Returns true if the FILE exists and is an executable file.
Also read:ย How to create Bash aliases?
