1. Overview

In this shell scripting tutorial, we’ll discuss how we can check whether a specified directory already exists.

First, we’ll cover the basics of checking whether a directory exists. Then, we’ll point out some caveats that might occur when we write shell scripts.

2. Checking Whether a Directory Exists in Shell

In this section, we’ll cover the POSIX way of checking for the existence of a directory.

On Linux, most shells provide built-in file test operators that we can use without having to rely on external tools. Of course, these built-in operators are POSIX compliant. Therefore, it’s easy to port our shell scripts when we use these operators.

2.1. The -d File Test Operator

The -d file test operator checks whether a specified directory exists. It evaluates to a boolean value.

Let’s create a temporary directory and see the -d test operator in action:

DIR="$(mktemp -d)"

if [ -d "$DIR" ]; then
  echo "$DIR exists."
fi

On the contrary, we can also test whether the directory doesn’t exist:

if [ ! -d "$DIR" ]; then
  echo "$DIR doesn't exist."
fi

As we can see, this is pretty straightforward, and we can also carry out the short-circuit evaluation:

$ [ -d "/tmp"] && echo "/tmp exists"
/tmp exists

Keep in mind that we should always enclose our filenames or filename variables in double quotes to prevent unexpected behavior.

For the most part, this should suffice for basic shell scripting. However, there are a few caveats that we might need to watch out for. Let’s get into that as well.

2.2. Dealing with Symlinks to a Directory

Sometimes, we may have symbolic links to the directory. For instance, let’s create a symlink to the /tmp directory:

$ ls -s /tmp t

Now, this symlink is not a regular directory, so we can’t perform a regular directory operation on it:

$ rmdir t
rmdir: failed to remove 't': Not a directory

For this reason, we’ll need to provide an additional check for the directory:

if [ -d "$DIR" ]; then
  if [ -L "$DIR" ]; then
    echo "$DIR is a symlink."
    # Treat $DIR as symlink
  else
    echo "$DIR is a regular directory."
    # Treat $DIR as directory
  fi
else
  echo "$DIR doesn't exist."
fi

The -L file test operator checks whether the specified filename is a symlink. If that is the case, we can treat this symlink as a regular file — for example, using rm instead of rmdir.

Alternatively, we can avoid this extra check for symlink by adding a forward slash at the end of the directory name:

if [ -d "${DIR}/" ]; then
  echo "$DIR is a regular directory."
else
  echo "$DIR doesn't exist."
fi

2.3. Resolving the Directory and Filenames Conflict

Sometimes, the code in the following snippet will behave unexpectedly:

if [ ! -d "$DIR" ]; then
  # Directory doesn't exist
  mkdir "$DIR"
fi

The test in the above snippet will evaluate to false for one of two reasons:

  • the $DIR doesn’t exist
  • the $DIR exists, but it isn’t a directory

For that reason, we can put another extra check to make sure that $DIR doesn’t exist as a file:

if [ ! -d "$DIR" -a ! -e "$DIR" ]; then
  # Directory doesn't exist
  # Safe to create $DIR
  mkdir "$DIR"
fi

The -e file test operator will check whether a file named $DIR exists. Therefore, creating the $DIR won’t clash with an existing file named $DIR as well.

3. Alternative: Using the find Tool

As an alternative to the -d file test operator, we can also use the find tool to check for the existence of a directory.

One of the reasons we might need to use find is if we want to check the existence of a directory that matches a certain pattern. Let’s check for a directory whose name starts with “photo” in the current directory:

if [ "$(find -maxdepth 1 -type d -name "photo*")" ]; then
  echo "$DIR exists."
else
  echo "$DIR doesn't exist."
fi

We can also carry out other useful checks that find is capable of, such as recursively checking for the existence of a directory in a filesystem tree or checking for a directory with specific permissions.

4. Alternative: Using the ls Command

Using ls is another alternative workaround to check for the existence of a directory:

if [ "$(ls -- "$DIR" 2> /dev/null)" ]; then
  echo "$DIR exists."
else
  echo "$DIR doesn't exist."
fi

5. Conclusion

In this tutorial, we saw how we could check for the existence of a given directory in a shell script. First, we used the basic -d file test operator. Afterward, we went through overcoming a few pitfalls that we might face.

Finally, we saw how we could use find and ls as alternatives to the -d file test operator.

Authors Bottom

If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

Comments are closed on this article!