Updated: 8 October 2026 · Applies to: bash 5.3 (Ubuntu 26.04), bash 5.2 (Debian 13, AlmaLinux 10) and POSIX sh (dash)
To check if a directory exists in Linux, use the -d test: [ -d "/path/to/dir" ] && echo "exists". It is true only when the path exists and is a directory. It works in bash, in plain sh scripts and straight at the command line. Always put the path or variable in double quotes.
1. One-line checks
# directory exists [ -d "/etc" ] && echo "Directory /etc exists." # directory does NOT exist [ ! -d "/nope" ] && echo "Directory /nope does not exist." # yes or no test -d /var/www && echo yes || echo no
test -d and [ -d ] are the same command. Both set the exit status, which scripts can use: 0 means the directory exists, 1 means it does not.
$ test -d /etc; echo "exit status: $?" exit status: 0 $ test -d /nope; echo "exit status: $?" exit status: 1
2. In a bash script: if, else
#!/bin/bash DIR="/etc/apache2" if [ -d "$DIR" ]; then echo "Installing config files in $DIR..." else echo "Error: $DIR not found. Cannot continue." >&2 exit 1 fi
A small script that checks the directory you pass to it:
#!/bin/bash
d="$1"
[ -z "$d" ] && { echo "Usage: $0 directory" >&2; exit 2; }
if [ -d "$d" ]; then
echo "Directory $d found."
else
echo "Directory $d not found."
exit 1
fi
Saved as checkdir.sh and made executable with chmod +x checkdir.sh, it gave:
$ ./checkdir.sh /tmp Directory /tmp found. $ ./checkdir.sh /rootadminz Directory /rootadminz not found.
3. Create the directory if it does not exist
d="$HOME/backup/2026" [ -d "$d" ] || mkdir -p "$d"
mkdir -p on its own is also safe: it does nothing if the directory is already there, and it creates missing parent folders.
4. Why the quotes matter
Two mistakes we reproduced on Ubuntu 26.04 and AlmaLinux 10:
- Empty variable: with
DIR="", the unquoted test[ -d $DIR ]returned true, because the shell sees only[ -d ]. The quoted[ -d "$DIR" ]correctly returned false. - Spaces in the path: with
DIR="/tmp/my files",[ -d $DIR ]failed with[: /tmp/my: binary operator expected.[ -d "$DIR" ]worked.
5. [ ] or [[ ]]?
In bash you can also write [[ -d $DIR ]]. Inside [[ ]] the variable is not split at spaces, so it worked even without quotes. But [[ ]] is bash only: on Ubuntu and Debian, /bin/sh is dash, and a #!/bin/sh script failed with [[: not found. On AlmaLinux and Rocky Linux, /bin/sh is bash, so the same script runs there, which hides the problem until you move it. For scripts that start with #!/bin/sh, use [ -d "$DIR" ].
6. Related tests
-e: the path exists (file, directory or anything else).-f: the path is a regular file.[ -d /tmp/afile ]was false for a file.-L: the path is a symbolic link.-dfollows links, so a link to a directory also counts as a directory.- Directory exists but is it empty?
if [ -n "$(ls -A "$d")" ]; then echo "not empty"; else echo "empty"; fi
7. Check several directories
for d in /etc /var/log /nope; do if [ -d "$d" ]; then echo "$d: yes"; else echo "$d: no"; fi done
Output: /etc: yes, /var/log: yes, /nope: no. A wildcard works too, for example for d in /home/*/public_html; do [ -d "$d" ] && echo "found $d"; done.
When a directory that exists looks missing
-d needs permission to look inside every parent folder. As a normal user, [ -d /root/private ] returned false because /root has mode 700, even though the folder exists. Run the check with sudo, or as the user the script really runs as (for example the web server user).
For the full list of tests, run help test in bash or man test. More bash: bash functions, bash arrays and redirect standard error.
Official documentation: Bash conditional expressions and test(1) manual.