How do I check if a directory exists in a Bash shell script?

Viewed 3041635

What command checks if a directory exists or not within a Bash shell script?

35 Answers

To check if a directory exists:

if [ -d "$DIRECTORY" ]; then
  echo "$DIRECTORY does exist."
fi

To check if a directory does not exist:

if [ ! -d "$DIRECTORY" ]; then
  echo "$DIRECTORY does not exist."
fi

However, as Jon Ericson points out, subsequent commands may not work as intended if you do not take into account that a symbolic link to a directory will also pass this check. E.g. running this:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

Will produce the error message:

rmdir: failed to remove `symlink': Not a directory

So symbolic links may have to be treated differently, if subsequent commands expect directories:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

Take particular note of the double-quotes used to wrap the variables. The reason for this is explained by 8jean in another answer.

If the variables contain spaces or other unusual characters it will probably cause the script to fail.

Always wrap variables in double quotes when referencing them in a Bash script.

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

Kids these days put spaces and lots of other funny characters in their directory names. (Spaces! Back in my day, we didn't have no fancy spaces!) One day, one of those kids will run your script with $DIRECTORY set to "My M0viez" and your script will blow up. You don't want that. So use double quotes.

Note the -d test can produce some surprising results:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

File under: "When is a directory not a directory?" The answer: "When it's a symlink to a directory." A slightly more thorough test:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

You can find more information in the Bash manual on Bash conditional expressions and the [ builtin command and the [[ compound commmand.

I find the double-bracket version of test makes writing logic tests more natural:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

Shorter form:

# if $DIR is a directory, then print yes
[ -d "$DIR" ] && echo "Yes"
  1. A simple script to test if a directory or file is present or not:

     if [ -d /home/ram/dir ]   # For file "if [ -f /home/rama/file ]"
     then
         echo "dir present"
     else
         echo "dir not present"
     fi
    
  2. A simple script to check whether the directory is present or not:

     mkdir tempdir   # If you want to check file use touch instead of mkdir
     ret=$?
     if [ "$ret" == "0" ]
     then
         echo "dir present"
     else
         echo "dir not present"
     fi
    

    The above scripts will check if the directory is present or not

    $? if the last command is a success it returns "0", else a non-zero value. Suppose tempdir is already present. Then mkdir tempdir will give an error like below:

    mkdir: cannot create directory ‘tempdir’: File exists

More features using find

  • Check existence of the folder within sub-directories:

      found=`find -type d -name "myDirectory"`
      if [ -n "$found" ]
      then
          # The variable 'found' contains the full path where "myDirectory" is.
          # It may contain several lines if there are several folders named "myDirectory".
      fi
    
  • Check existence of one or several folders based on a pattern within the current directory:

      found=`find -maxdepth 1 -type d -name "my*"`
      if [ -n "$found" ]
      then
          # The variable 'found' contains the full path where folders "my*" have been found.
      fi
    
  • Both combinations. In the following example, it checks the existence of the folder in the current directory:

      found=`find -maxdepth 1 -type d -name "myDirectory"`
      if [ -n "$found" ]
      then
          # The variable 'found' is not empty => "myDirectory"` exists.
      fi
    
DIRECTORY=/tmp

if [ -d "$DIRECTORY" ]; then
    echo "Exists"
fi

Try online

Actually, you should use several tools to get a bulletproof approach:

DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # Now you're testing
    echo "It's a dir";
fi

There isn't any need to worry about spaces and special characters as long as you use "${}".

Note that [[]] is not as portable as [], but since most people work with modern versions of Bash (since after all, most people don't even work with command line :-p), the benefit is greater than the trouble.

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

This is not completely true...

If you want to go to that directory, you also need to have the execute rights on the directory. Maybe you need to have write rights as well.

Therefore:

if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
    # ... to go to that directory (even if DIRECTORY is a link)
    cd $DIRECTORY
    pwd
fi

if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
    # ... to go to that directory and write something there (even if DIRECTORY is a link)
    cd $DIRECTORY
    touch foobar
fi

Use the file program. Considering all directories are also files in Linux, issuing the following command would suffice:

file $directory_name

Checking a nonexistent file: file blah

Output: cannot open 'blah' (No such file or directory)

Checking an existing directory: file bluh

Output: bluh: directory

One Liner:

[[ -d $Directory ]] && echo true

Just as an alternative to the '[ -d ]' and '[ -h ]' options, you can make use of stat to obtain the file type and parse it.

#! /bin/bash
MY_DIR=$1
NODE_TYPE=$(stat -c '%F' ${MY_DIR} 2>/dev/null)
case "${NODE_TYPE}" in
        "directory") echo $MY_DIR;;
    "symbolic link") echo $(readlink $MY_DIR);;
                 "") echo "$MY_DIR does not exist";;
                  *) echo "$NODE_TYPE is unsupported";;
esac
exit 0

Test data:

$ mkdir tmp
$ ln -s tmp derp
$ touch a.txt
$ ./dir.sh tmp
tmp
$ ./dir.sh derp
tmp
$ ./dir.sh a.txt
regular file is unsupported
$ ./dir.sh god
god does not exist
Related