How to mkdir only if a directory does not already exist?

1,623,583

Solution 1

Try mkdir -p:

mkdir -p foo

Note that this will also create any intermediate directories that don't exist; for instance,

mkdir -p foo/bar/baz

will create directories foo, foo/bar, and foo/bar/baz if they don't exist.

Some implementation like GNU mkdir include mkdir --parents as a more readable alias, but this is not specified in POSIX/Single Unix Specification and not available on many common platforms like macOS, various BSDs, and various commercial Unixes, so it should be avoided.

If you want an error when parent directories don't exist, and want to create the directory if it doesn't exist, then you can test for the existence of the directory first:

[ -d foo ] || mkdir foo

Solution 2

This should work:

$ mkdir -p dir

or:

if [[ ! -e $dir ]]; then
    mkdir $dir
elif [[ ! -d $dir ]]; then
    echo "$dir already exists but is not a directory" 1>&2
fi

which will create the directory if it doesn't exist, but warn you if the name of the directory you're trying to create is already in use by something other than a directory.

Solution 3

Use the -p flag.

man mkdir
mkdir -p foo

Solution 4

Defining complex directory trees with one command

mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}

Solution 5

If you don't want to show any error message:

[ -d newdir ] || mkdir newdir

If you want to show your own error message:

[ -d newdir ] && echo "Directory Exists" || mkdir newdir
Share:
1,623,583
Spike Williams
Author by

Spike Williams

Of all the code I've written in my life, probably the javascript eight ball I wrote on a lark one night over a decade ago is the thing that's had the most impact in the world. So it goes.

Updated on July 08, 2022

Comments

  • Spike Williams
    Spike Williams almost 2 years

    I am writing a shell script to run under the KornShell (ksh) on AIX. I would like to use the mkdir command to create a directory. But the directory may already exist, in which case I do not want to do anything. So I want to either test to see that the directory does not exist, or suppress the "File exists" error that mkdir throws when it tries to create an existing directory.

    How can I best do this?

  • Alnitak
    Alnitak about 15 years
    wrong on both counts, AFAIK. tests return true on success, and -d exists too (at least on MacOS X)
  • Mike Q
    Mike Q about 10 years
    This will fail if "tmp" did not exist. nor does it give you any confirmation.
  • Mike Q
    Mike Q about 10 years
    the shortened example you use is exactly what you should not do. It is reversing the logic to save coding space but it should use ! and && and make more sense to those reading it.
  • angularsen
    angularsen over 9 years
    On Windows8 it seems -p is no longer supported and it's the default behavior.
  • Brian Campbell
    Brian Campbell over 9 years
    @AndreasLarsen This question is about mkdir on Unix-like systems, not on Windows. -p is required for POSIX/Single Unix Specification compliance, so anything that intents to comply with those specifications will support -p. Windows is entirely different, unless you use a POSIX emulation layer like Cygwin or MSYS.
  • Justin L.
    Justin L. over 9 years
    it might be worth mentioning that this isn't quite thread-safe. between the time that you check if the directory exists and the time you try to write, things might change.
  • uliwitness
    uliwitness about 9 years
    As mentioned by @BrianCampbell, this will also create any other directories in the path. This can be dangerous if e.g. a volume becomes unmounted, as it may create directories in the mount point.
  • herve
    herve over 8 years
    I discovered something interesting today with mkdir -p, you can use brackets! {} to create "complex" directory tree in a command. See here: technosophos.com/2010/04/15/…
  • rudimeier
    rudimeier over 8 years
    @MikeQ I 'd prefer || instead of && because then the whole line has the right exit status. Important if your shell runs with errexit or if that line is the last one in a function, switch-case, whatever.
  • Zsigmond Lőrinczy
    Zsigmond Lőrinczy over 8 years
    Or: mkdir somedir 2>/dev/null || true
  • Fedir RYKHTIK
    Fedir RYKHTIK about 8 years
    no error if existing, make parent directories as needed
  • Daniel Kamil Kozar
    Daniel Kamil Kozar about 8 years
    Keep in mind that this is not a feature of mkdir itself, but the shell that executes the command. It's called brace expansion - AFAIK, only Bash, ksh, zsh, and the C shell support it.
  • J. Chomel
    J. Chomel about 7 years
    OP was about AIX kornshell... nothing to do with Windows, does it?
  • Atlas7
    Atlas7 almost 7 years
    if you have spaces around the commas you may (will) get unexpected result. Beware.
  • chepner
    chepner over 6 years
    @herve That has nothing to do with mkdir; the shell expands such an expression to a discrete list of argument that are passed to mkdir.
  • John Hamilton
    John Hamilton over 6 years
    @Atlas7 stated, you will need to escape characters that are normally part of regex. (i.e. instead of using folder name you need to use folder\ name)
  • pedram bashiri
    pedram bashiri almost 6 years
    Is there any advantage in using if loop!? why would someone choose that over -p option?!
  • AbhinavVaidya8
    AbhinavVaidya8 almost 6 years
    I have shared you ways of creating the folders when an folder does not exists. It depends upon the requirement on the one. If you have a use case where you need to check if folder does not exist and you want to keep track of that so you can go with solution 1. If it does not matter, you can go with solution 2, it will create the folder if not exists.
  • akozi
    akozi almost 6 years
    Does this work with a wild card before the intermediate steps? Ex /*/foo/bar/baz ?
  • Brian Campbell
    Brian Campbell over 5 years
    @akozi Yes, if the appropriate directories already exist at the level that the wild card is used. In the shell, glob expansion happens before passing the arguments to the program (mkdir, in this case). So if you had directories a, b, and c, mkdir -p */foo/bar/baz would be the same as mkdir -p a/foo/bar/baz b/foo/bar/baz c/foo/bar/baz. mkdir can take multiple arguments, and when given -p, it will create needed intermediate directories. Experiment with this yourself. Try echo mkdir -p */foo/bar/baz to see what command is run; or just try running it in a test directory.
  • Chris Page
    Chris Page over 4 years
    This is not an answer; this is a separate topic that would be more appropriate as a comment.
  • Peter Mortensen
    Peter Mortensen about 4 years
    Race conditions? Can you elaborate in your answer? Non-atomic test & create?
  • Peter Mortensen
    Peter Mortensen about 4 years
    Defining? Do you mean creating?
  • Peter Mortensen
    Peter Mortensen about 4 years
  • Peter Mortensen
    Peter Mortensen about 4 years
    Are you sure it was supported before? Do you have a source?
  • paxdiablo
    paxdiablo about 4 years
    @Peter, a snippet like (for example) [ -d newdir ] || mkdir newdir, where the directory does not initially exist, has a race condition in that, between the test for existence and the attempted creation, another process could swoop in and create the directory. Hence the mkdir would then fail.
  • Jahid
    Jahid about 4 years
    @PeterMortensen : Of course. Use mkdir -p if you do not want race conditions. But you won't get to show your own Directory exists error.
  • RicarHincapie
    RicarHincapie almost 4 years
    @herve discovery is very handy. Please remember not to leave whitespaces in any part of this script.
  • Shankara Narayana
    Shankara Narayana about 3 years
    -p, --parents no error if existing, make parent directories as needed
  • hakre
    hakre about 3 years
    @Mike Q: the base path /tmp has likely been chosen in the example to represent a base-path that always exists and is write-able to the current user, e.g. the user has enough rights to create a directory in. You raise a valid point thought:: the logic is a bit contradictory, as when this command fails, it can mean two things: 1.) the directory exists or 2.) the directory could not be created. This is not true for the operation itself, therefore a simple post-check on the directory path can give the confirmation, or the next command that operates on.
  • edoardesd
    edoardesd over 2 years
    It should be: mkdir -p /my/new/dir >/dev/null 2>&1
  • Leevi L
    Leevi L over 2 years
    mkdir -p my/new/dir does not complain if my/new/dir already exists, no need to redirect output
  • moodboom
    moodboom over 2 years
    Typo fixed. Leevi, I believe I ran into a situation where the output needed to be squelched.
  • Jesse Nickles
    Jesse Nickles over 2 years
    mkdir -p /tmp/qq > /dev/null 2>&1 will create /tmp/ if missing.
  • dube
    dube about 2 years
    note for naiive windows users: -p still fails on windows when the folder exists
  • Jeppe
    Jeppe about 2 years
    @herve Awesome! Just realized it works for other commands as well, e.g. to create 3 files: touch {a,b,c}.txt