views:

67213

answers:

11

What command can be used to check if a directory does or does not exist, within a bash shell script?

+66  A: 

To check if a directory exists in a bash shell script you can use the following:

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

Or to check if a directory doesn't exist:

if [ ! -d "$DIRECTORY" ]; then
    # Control will enter here if $DIRECTORY doesn't exist
fi

However, as Jon Ericson points out (thanks Jon), 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 "$SYMLINK"
    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.

Grundlefleck
If you want to play it safe with the GNU tools, use of `--` is highly recommended (end-of-options marker). Otherwise, if your variable contains something that looks like an option, the script'll fail just as with spaces.
It might be worth mentioning that [ ... ] is syntactic sugar for the 'test' command. Useful information because without it you might not know you can do 'man test' to get the documentation.
Bryan Oakley
This comment is even more important than the anwser :-)
e-satis
+1  A: 

You could use the find command

found=`find -type d -name "myDirectory"`
if [ -n "$found"]
then
    # found is not empty
fi
Neil Neyman
Watch out! find will recurse through subdirectories, which might not be what you want. See <http://beta.stackoverflow.com/questions/27077/is-there-any-way-to-prevent-find-from-digging-down-recursively-into-subdirector>. Also, the first argument to find must be the path list.
Jon Ericson
+5  A: 

@ Grundlefleck

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

(I'd have made this a comment, since it's not really the right answer, just an elaboration on the right answer, but the comment box is far too constraining. Feel free to add this material to the answer itself.)

Jon Ericson
Thanks Jon, good point. I have taken it on board and included it in my own answer. Hope you don't mind the alterations!
Grundlefleck
+1  A: 

or even shorter: [ -d / ] && echo "Yes"

elmarco
Even shorter: echo "Yes". [ -d / ] should always be true or you will have much bigger problems. ;-)
Jon Ericson
+17  A: 

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

And I see that the double-bracket operator is often faster.

yukondude
Thanks for the hint with double brackets, it's great!
furtelwart
+9  A: 

Grundlefleck wrote:

if [ -d $DIRECTORY ]; then

Remember to always wrap variables in double quotes when interpolating them in a bash script. Kids these days grow up with the idea that they can have spaces and lots of other funny characters in their directory names. (Spaces! Back in my days, we didn't have no fancy spaces!) ... ;)

One day, one of those kids will run your script with $DIRECTORY set to "My M0viez" and you script will blow up. You don't want that. So use

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

instead.

8jean
Another reason to use double quotes is in case $DIRECTORY is not set for some reason.
Jon Ericson
Thanks, I'll incorporate that into my answer.
Grundlefleck
A: 

Or for something completely useless:

[ -d . ] || echo "No"
A: 

Actually, you should use several tools to get a bullet proof 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

No 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.

e-satis
A: 
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 needs to have the execute rights on the directory. Maybe you need to have write rights as well.

Therfore:

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
TheBear
I think that the original comment indicated that the control of the script would enter there, not that the script would enter that directory.
dreamlax
@TheBear: dreamlax is correct, I'll try to make that clearer in the answer.
Grundlefleck
A: 

No need to check to see if DIR or SYMLINK to issue separate RM or RMDIR commands. Just use rm -rf (-r recusively remove and -f means force, no prompts)

I'd also check that you aren't attempting to remove "/" (root) or current directory.

if [ -d "$DIR" ] && [ "$DIR" != "/" ] && [ "$DIR" != "." ] && [ "$DIR" != "./" ]; then rm -rf $DIR fi

joexpert
A: 
if [ -d "$Directory" -a -w "$Directory" ] 
then
 #Statements
fi

Above code check if directory exists and and if it is writable.

-MuraliKrishna.B

muralikrishna