How To Check If a Directory Exists In a Shell Script

How do I check if a directory exists in a shell script under Linux or Unix like operating systems? How can I check if a directory exists in a shell script on Unix-like system?

To check if a directory exists in a shell script and is a directory use the following syntax:
[ -d "/path/to/dir" ] && echo "Directory /path/to/dir exists."
[ ! -d "/path/to/dir" ] && echo "Directory /path/to/dir DOES NOT exists."
OR combine both of them in a single go:
[ -d "/path/to/dir" ] && echo "Directory /path/to/dir exists." || echo "Error: Directory /path/to/dir does not exists."
Tutorial details
DifficultyEasy (rss)
Root privilegesNo
The following version also check for symbolic link:
[ -d "/path/to/dir" && ! -L "/path/to/dir" ] && echo "Directory /path/to/dir exists." || echo "Error: Directory /path/to/dir exists but point to $(readlink -f /path/to/dir)."
[ -d "/path/to/dir" && ! -h "/path/to/dir" ] && echo "Directory /path/to/dir exists." || echo "Error: Directory /path/to/dir exists but point to $(readlink -f /path/to/dir)."
Finally, you can use the traditional bash syntax as follows:


if [ -d "/path/to/dir" ] 
    echo "Directory /path/to/dir exists." 
    echo "Error: Directory /path/to/dir does not exists."


### Check if a directory does not exist ###
if [ ! -d "/path/to/dir" ] 
    echo "Directory /path/to/dir DOES NOT exists." 
    exit 9999 # die with error code 9999

Shell script examples to see if a ${directory} exists or not

The following script also demos the use of readlink command to print value of a symbolic link or canonical file name.

# dirtest.bash - Demo script by nixCraft under GPL v2.x+
# -------------------------------------------------------
[ $# -eq 0 ] && { echo "Usage: $0 dir-name"; exit 1; }
if [ -d "$dir" -a ! -h "$dir" ]
   echo "$dir found and setting up new Apache/Lighttpd/Nginx jail, please wait..."
   # __WWWJailSetup "" "setup"
   echo "Error: $dir not found or is symlink to $(readlink -f ${dir})."

Save and run it as follows:

$ chmod +x dirtest.bash
$ ./dirtest.bash
$ ./dirtest.bash /home/httpd
$ ./dirtest.bash /var/www

Sample outputs:

Fig.01: Shell script in action

Fig.01: Shell script in action

In this example, create directories if does not exists:

# Purpose: Setup jail and copy files
# Author: nixCraft <> under GPL v2.x+
# Category : Core
# Override : No
# Parameter(s) : d => domain name
#                action => setup or update
        local d="$1"
        local action="${2:setup}"       # setup or update???
        local index="<html><head><title>$d</title></head><body><h1>$d</h1></body></html>" # default index.html
        local J="$(_getJailRoot $d)/$d" # our sweet home 
        local _i=""
        [ "$action" == "setup" ] && echo "* Init jail config at $J..." || echo "* Updating jail init config at $J..."
        __init_domain_config "$d"
        [ "$action" == "setup" ] && echo "* Setting up jail at $J..." || echo "* Updating jail at $J..."
        [ ! -d "$J" ] &&  $_mkdir -p "$J"
        for _i in $J/{etc,tmp,usr,var,home,dev,bin,lib64}
                [ ! -d "$_i" ] &&  $_mkdir -p "$_i"
        for _i in $_lighttpd_webalizer_base/$d/stats/{dump,out}
                [ ! -d "$_i" ] &&  $_mkdir -p "$_i"
        for _i in $_lighttpd_webalizer_prepost_base/$d/{pre.d,post.d}
                [ ! -d "$_i" ] &&  $_mkdir -p "$_i"
## truncated 


Use the following to check file/directory types and compare values:

  1. -L "FILE" : FILE exists and is a symbolic link (same as -h)
  2. -h "FILE" : FILE exists and is a symbolic link (same as -L)
  3. -d "FILE" : FILE exists and is a directory
  4. -w "FILE" : FILE exists and write permission is granted

We learned how to check if a directory exists in a shell script using the test command

🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source/DevOps topics:
CategoryList of Unix and Linux commands
File Managementcat
Network Utilitiesdig host ip nmap
Package Managerapk apt
Processes Managementbg chroot disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w

7 comments… add one
  • Gilles Apr 14, 2013 @ 20:32

    I sometime use “[ -x $dir/. ]”, to check at the same time if directory exist and if the calling process has traverse rights on it.

  • chukaman Aug 23, 2013 @ 6:18

    “exits” “exits” “exits” all over the place where you had intended to write “exists”. you might want to change that.

  • Peter Mar 1, 2016 @ 14:31

    i love this one:

    [[ -d dir ]] || mkdir dir

    • Apr 21, 2016 @ 2:08

      Isn’t that same as `mkdir -p dir`?

      • 🐧 Vivek Gite May 2, 2017 @ 12:29

        You can do a little bit customization like:
        [[ -d dir ]] || { echo "Dir not found...creating..."; mkdir dir; /path/to/call/something/init; }

  • Curtis Sep 29, 2017 @ 2:47

    I really like this one for setting a variable to a file path only if it exists. From what I can tell, this is probably amongst the most efficient methods of doing such a task.

    Lets assume we have the following:

    Using bash’s builtin “type” the “-P” does a PATH search, only printing if the filename is found within the path, irrespective of the executable state:

    $ VAR1=$(PATH=/path/to type -P file)
    $ echo $VAR1

    What is really neat about this is that we can use it to see if the file exists in several places, using the order of the temporary PATH to indicate preferences.

    Let’s add a couple files for an example:

    Now if we want to set “file” as a variable, and know it should be in one of three places, we can do…

    $ VAR2=$(PATH=/path/to/other:/path/to:/other/directory type -P file)
    $ echo $VAR2

    But what if /path/to takes precedence? An example is any program that gives configs in /etc priority over /usr/lib if identically named (ie. systemd, modprobe.d, etc.). We can use the PATH order to match by level of significance…

    $ VAR3=$(PATH=/path/to:/path/to/other:/other/directory type -P file)
    $ echo $VAR3

    Bash’s builtin “type” is quite nice in that upon failure, it prints nothing. So you don’t even need to throw out stderr with “2>/dev/null”!

    $ VAR4=$(/path/to:/path/to/other:/other/directory type -P baz)
    $ echo $VAR4


    Even if you did “echo $FARTBRAINS” it still creates a nice \n for you, even if you’ve never even remotely thought about using that variable name. So VAR4 is essentially unset. Neat!

    Usually I’m a zsh user. Zsh’s “whence” and “which” come closest, but cannot search beyond executables and print a short fail message (that I’d otherwise not mind). I’m sure other shells might behave similarly, but those are the two I’ve tested. I script with bash anyway.

    Unfortunately, I have not come up with a way to do directories in a similar manner. I really searched through the bash shell builtin documentation and google-fu’ed the best I could, but I cannot figure anything out that is that efficient.

    Hopefully someone smarter than me can prove there is a way. I don’t know if I’ll ever check this page again… and don’t know why I just put so much work into this comment. But I hope you enjoyed!

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.