What Are the Most Reliable Ways to Check if a Directory or File Exists in Linux Using Shell Scripts?
In Linux, ensuring the existence and type of a file or directory is a critical part of shell scripting, especially when automating system tasks or hardening configurations. This blog explains how to check if a file or directory exists, determine its type (regular file, directory, symbolic link, etc.), and validate its permissions—all using built-in shell commands. Learn how the [ command works in practice, and explore a detailed table of all test options like -e, -f, -d, -x, and more. Whether you're scripting system backups, server hardening routines, or automated tasks, this guide will help you avoid common pitfalls and ensure your scripts behave reliably in production environments.

Table of Contents
- Why File and Directory Checks Matter in Shell Scripts
- Basic Syntax: Test Command or Square Brackets
- Check if a File Exists (
-e
Option) - Check if a File is a Regular File (
-f
Option) - Check if a File is Executable (
-x
Option) - Check if a Directory Exists (
-d
Option) - Full List of Test Options
- Bonus Tip: Check Built-in Bash Commands
- Practical Use Case in Automation Scripts
- Conclusion
- Frequently Asked Questions (FAQs)
When working with Linux shell scripts, verifying the presence of a directory or file is a foundational skill for system administrators and DevOps professionals. Whether you're performing automated backups, validating configuration files, or ensuring executable scripts are in place, knowing how to test for file types and permissions can prevent costly runtime errors.
In this blog, we’ll cover how to check if a file or directory exists in Linux, how to determine the type of file, whether it's executable, and explore advanced test options—all with examples.
Why File and Directory Checks Matter in Shell Scripts
Linux is powerful, but it assumes you know what you're doing. If your script tries to read a file that doesn't exist or write to a non-existent directory, it will fail. That’s why checking for file or directory existence before performing operations is a best practice.
Basic Syntax: Test Command or Square Brackets
In shell scripting, you can use either:
test
Or the commonly used equivalent:
[ ]
✅ Tip: The
[
is actually a command itself, and requires a closing]
.
✅ Check if a File Exists (-e
Option)
To simply check if a file exists:
MYFILE="/etc/passwd"
if [ -e "${MYFILE}" ]; then
echo "File exists"
fi
✅ Check if a File is a Regular File (-f
Option)
Use this when you want to ensure it’s not a directory or special file:
MYFILE="/etc/passwd"
if [ -f "${MYFILE}" ]; then
echo "File exists and is a regular file"
fi
✅ Check if a File is Executable (-x
Option)
This is useful when working with scripts or binaries:
MYFILE="/usr/bin/bash"
if [ -x "${MYFILE}" ]; then
echo "File is executable"
fi
✅ Check if a Directory Exists (-d
Option)
Directory checks are commonly used when working with logs, configs, or backups:
ETCDIR="/etc"
if [ -d "${ETCDIR}" ]; then
echo "Directory ${ETCDIR} exists"
else
echo "Error: Directory ${ETCDIR} does not exist"
exit 1
fi
Full List of Test Options
Here’s a comprehensive table of test options available in Bash:
Option | Purpose |
---|---|
-b |
File exists and is a block special file |
-c |
File exists and is a character special file |
-d |
File exists and is a directory |
-e |
File exists (regardless of type) |
-f |
File exists and is a regular file |
-g |
File exists and has the set-group-ID (SGID) bit set |
-G |
File exists and is owned by the effective group ID |
-h / -L |
File exists and is a symbolic link |
-k |
File exists and has the sticky bit set |
-N |
File exists and was modified since last read |
-O |
File exists and is owned by the effective user ID |
-p |
File exists and is a named pipe |
-r |
File exists and is readable |
-s |
File exists and its size is greater than zero bytes |
-S |
File exists and is a socket |
-t |
File descriptor is open and refers to a terminal |
-u |
File exists and has the set-user-ID (SUID) bit set |
-w |
File exists and is writable |
-x |
File exists and is executable or searchable (for directories) |
Bonus Tip: Check Built-in Bash Commands
To see if [
is a built-in command in your shell:
compgen -b | grep '\['
You’ll likely find that [
is a shell builtin in Bash, which means it's faster than using the external /usr/bin/test
.
Practical Use Case in Automation Scripts
Example: Backup Script with File and Directory Checks
BACKUP_DIR="/mnt/backup"
CONFIG_FILE="/etc/app/config.yaml"
if [ -d "${BACKUP_DIR}" ] && [ -f "${CONFIG_FILE}" ]; then
cp "${CONFIG_FILE}" "${BACKUP_DIR}"
echo "Backup successful"
else
echo "Backup failed. Check if directory and file exist."
exit 1
fi
Conclusion
Understanding how to check if a file or directory exists in Linux is crucial for writing robust shell scripts. By using the test
or [
command with appropriate options like -f
, -d
, or -x
, you can ensure your scripts don’t break when files are missing or inaccessible.
Use the provided table as a quick reference for all the file test options, and apply these in your automation and system management tasks.
FAQs
What command checks if a file exists in Linux?
The test
command or its symbolic form [
is used in Linux to check file existence. For example: if [ -e /path/to/file ]; then
.
How to check if a directory exists in a shell script?
Use the -d
option with [
like this: if [ -d /path/to/dir ]; then
.
What does -f
check in Linux?
It checks if the file exists and is a regular file.
Is there a difference between -e
and -f
?
Yes, -e
checks for the existence of any file, while -f
ensures it's a regular file.
Can I check if a file is executable in a script?
Yes, use -x
to test if a file has execute permissions.
How to check symbolic links in Linux scripts?
Use -h
or -L
to test if a file is a symbolic link.
What's the command to check if a file is readable?
Use -r
to test read permissions on a file.
How do I test if a file has write permissions?
Use -w
to check for write access.
What does -s
do in a file test?
Checks if the file exists and is not empty.
How can I test if a file is owned by a user in Linux?
Use -O
to test if a file is owned by the effective user ID.
What's the -b
file test used for?
It checks if a file is a block special file (e.g., disk device).
How can I test for character device files in shell?
Use -c
to test if a file is a character special file.
How do I check for a named pipe in bash?
Use the -p
test option.
What does -g
check in Linux?
It tests if a file has the setgid bit set.
Can I check if a file was modified since it was last read?
Yes, use the -N
option.
What does -G
test in a shell script?
Checks if the file is owned by the effective group ID.
How do I check if a file has the sticky bit set?
Use the -k
option for that.
Is there a way to test for socket files in bash?
Yes, use -S
to check if a file is a socket.
How do I test if a file descriptor is open on a terminal?
Use -t
followed by the file descriptor number.
How do I check if a file has the setuid bit set?
Use -u
to test for the setuid bit.
What is the difference between [ ... ]
and [[ ... ]]
in bash?
[ ... ]
is POSIX-compliant, while [[ ... ]]
is bash-specific with more features.
Can I use if test ...
instead of [ ... ]
?
Yes, test
and [
are functionally equivalent.
What if I want to check multiple conditions at once?
Use &&
or ||
operators, or combine tests with -a
and -o
.
What does the error “unary operator expected” mean?
It often means that a variable used in a test was undefined.
Can I check file permissions using octal values in bash?
Not directly; use stat
for detailed permission checks.
How do I make my script exit if a directory doesn’t exist?
Use:
Is it possible to use wildcards in test conditions?
Not directly in [
—use globbing or loop over results with for
.
Can I check file existence without error output?
Redirect errors to /dev/null
:
How to test file existence in one line?
What is the best practice for checking directories in scripts?
Always quote variables and include error handling: