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. -d follows 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.

Related services

KVM VPS hosting

NVMe SSD and full root access, with Free Basic Managed Support.

Unmanaged dedicated servers

full root access and free IPMI KVM, with Free Basic Managed Support.

Managed dedicated servers

our engineers look after the server for you, from $135 a month.

Was this answer helpful?

Still stuck? Open a ticket