How do I check if a directory exists or not in a Bash shell script?
Categories:
How to Check if a Directory Exists in Bash Shell Scripts

Learn various robust methods to verify the existence of a directory in Bash shell scripts, ensuring your scripts handle file system interactions gracefully and prevent errors.
When writing Bash shell scripts, it's a common requirement to check if a specific directory exists before performing operations like creating files within it, navigating into it, or deleting its contents. Failing to do so can lead to script errors, unexpected behavior, or even data loss. This article will guide you through the most reliable and idiomatic ways to check for directory existence in Bash, along with best practices.
Using the test
Command ([ ]
)
The test
command, often used in its shorthand form [ ]
, is the most fundamental way to perform conditional checks in Bash. It provides several operators for testing file attributes, including directory existence. The -d
operator specifically checks if a given path refers to an existing directory.
# Basic check for directory existence
DIR_PATH="/path/to/my/directory"
if [ -d "$DIR_PATH" ]; then
echo "Directory '$DIR_PATH' exists."
else
echo "Directory '$DIR_PATH' does not exist."
fi
# Example with creating if not exists
NEW_DIR="/tmp/my_new_dir"
if [ ! -d "$NEW_DIR" ]; then
echo "Directory '$NEW_DIR' does not exist. Creating it..."
mkdir -p "$NEW_DIR"
if [ $? -eq 0 ]; then
echo "Directory '$NEW_DIR' created successfully."
else
echo "Failed to create directory '$NEW_DIR'."
fi
else
echo "Directory '$NEW_DIR' already exists."
fi
Basic usage of [ -d ]
to check and conditionally create a directory.
"$DIR_PATH"
) within [ ]
or [[ ]]
to prevent issues with spaces or special characters in file paths. This is a crucial best practice for robust shell scripting.Using the [[ ]]
Compound Command
The [[ ]]
compound command is an enhanced version of [ ]
available in Bash (and other modern shells like Zsh and Ksh). It offers more advanced features, such as pattern matching and improved handling of word splitting, making it generally safer and more flexible for conditional expressions. It also supports the -d
operator for directory checks.
# Using [[ -d ]] for directory existence check
TARGET_DIR="/var/log/nginx"
if [[ -d "$TARGET_DIR" ]]; then
echo "Directory '$TARGET_DIR' exists and is a directory."
else
echo "'$TARGET_DIR' is not an existing directory."
fi
# Combining with other checks (e.g., readability)
ANOTHER_DIR="/etc/passwd.d" # This might not exist or be a directory
if [[ -d "$ANOTHER_DIR" && -r "$ANOTHER_DIR" ]]; then
echo "Directory '$ANOTHER_DIR' exists and is readable."
else
echo "Directory '$ANOTHER_DIR' either doesn't exist, isn't a directory, or isn't readable."
fi
Checking directory existence with [[ -d ]]
and combining conditions.
flowchart TD A[Start Script] --> B{Directory Path Provided?} B -- No --> C[Error: Path Missing] B -- Yes --> D{Check if Path Exists and is Directory?} D -- Yes (Exists) --> E[Perform Directory Operations] D -- No (Does Not Exist) --> F{Should Directory Be Created?} F -- Yes --> G[Create Directory] G --> E F -- No --> H[Exit or Handle Error] E --> I[End Script] C --> I H --> I
Decision flow for checking and handling directory existence in a script.
Alternative: Using find
for More Complex Scenarios
While [ -d ]
and [[ -d ]]
are perfect for simple checks, sometimes you might need to find a directory with specific attributes or within a larger search scope. The find
command is powerful for such scenarios, though it's generally overkill for a simple existence check.
# Check if a directory named 'logs' exists directly under /var
if find /var -maxdepth 1 -type d -name "logs" -print -quit | grep -q .; then
echo "Directory 'logs' found under /var."
else
echo "Directory 'logs' not found under /var."
fi
# More direct check using find and its exit status
# This is less efficient than [ -d ] for a single path
DIR_TO_CHECK="/opt/app/data"
if find "$DIR_TO_CHECK" -maxdepth 0 -type d > /dev/null 2>&1; then
echo "'$DIR_TO_CHECK' exists and is a directory (using find)."
else
echo "'$DIR_TO_CHECK' does not exist or is not a directory (using find)."
fi
Using find
for directory existence, suitable for more complex searches.
find
for a simple directory existence check on a known path is generally less efficient and more complex than using [ -d ]
or [[ -d ]]
. Reserve find
for scenarios where you need to search for directories based on criteria across a file system.Best Practices and Considerations
When checking for directory existence, keep the following best practices in mind to write robust and maintainable scripts:
1. Prioritize [[ -d ]]
for Modern Bash
For scripts intended for Bash 3.x and newer, [[ -d ]]
is generally preferred over [ -d ]
due to its enhanced features and safer handling of variables and special characters. It's more forgiving and less prone to subtle errors.
2. Always Quote Variables
As mentioned, always enclose your directory path variables in double quotes (e.g., "$MY_DIR"
) within conditional expressions. This prevents word splitting and globbing issues, especially if paths contain spaces or wildcards.
3. Handle Non-Existence Gracefully
Decide how your script should behave if a directory doesn't exist. Should it create the directory (mkdir -p
)? Should it exit with an error? Or should it simply skip an operation? Plan for these scenarios to prevent script failures.
4. Check Permissions if Necessary
Existence doesn't imply usability. If your script needs to write to a directory, you might also want to check for write permissions using -w
(e.g., [[ -d "$DIR" && -w "$DIR" ]]
).
5. Use mkdir -p
for Creation
When creating directories, mkdir -p
is invaluable as it creates parent directories as needed and does not throw an error if the directory already exists, simplifying your logic.