2267

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?

Jesse Nickles
  • 548
  • 1
  • 4
  • 17
Spike Williams
  • 29,764
  • 13
  • 43
  • 57

16 Answers16

3771

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
Brian Campbell
  • 289,867
  • 55
  • 346
  • 327
  • 11
    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. – Mike Q Jun 16 '14 at 17:36
  • 2
    On Windows8 it seems -p is no longer supported and it's the default behavior. – angularsen Oct 09 '14 at 09:00
  • 20
    @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. – Brian Campbell Oct 09 '14 at 15:54
  • 32
    I discovered something interesting today with `mkdir -p`, you can use brackets! `{}` to create "complex" directory tree in a command. See here: http://technosophos.com/2010/04/15/mkdir-creating-multiple-subdirectories-one-command.html – herve Feb 04 '16 at 11:13
  • 14
    @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. – rudimeier Mar 13 '16 at 15:42
  • Or: `mkdir somedir 2>/dev/null || true` – Zsigmond Lőrinczy Mar 25 '16 at 18:53
  • 9
    @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`. – chepner Oct 31 '17 at 20:33
  • 2
    You are definitely right. Still, it is really powerful in that case. – herve Nov 01 '17 at 17:52
  • @herve Thank you for that! Definitely was not aware of it and it will come in handy in the future! – Victor Ude Jul 19 '18 at 21:55
  • Does this work with a wild card before the intermediate steps? Ex /*/foo/bar/baz ? – akozi Sep 17 '18 at 17:38
  • 1
    @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. – Brian Campbell Jan 23 '19 at 21:14
  • @herve discovery is very handy. Please remember not to leave whitespaces in any part of this script. – RicarHincapie Aug 17 '20 at 23:03
196

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.

Alnitak
  • 313,276
  • 69
  • 379
  • 466
  • I don't think there's a -d operator in korn, rather -e is used for both files / directories and just checks existence. Also, they all return 0 upon success, so ! is redundant. Correct me if I'm wrong. – alkar Apr 27 '09 at 14:57
  • 1
    wrong on both counts, AFAIK. tests return _true_ on success, and -d exists too (at least on MacOS X) – Alnitak Apr 27 '09 at 14:58
  • 6
    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. – Justin L. Mar 12 '15 at 01:27
95

Use the -p flag.

man mkdir
mkdir -p foo
jimmyorr
  • 9,652
  • 4
  • 28
  • 20
78

Defining complex directory trees with one command

mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
Oleg
  • 809
  • 6
  • 3
44

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
Jahid
  • 18,228
  • 8
  • 79
  • 95
  • 1
    But [subject to race conditions](https://stackoverflow.com/questions/793858/how-to-mkdir-only-if-a-dir-does-not-already-exist/793916#793916)? – Peter Mortensen Jun 12 '20 at 18:05
  • @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. – Jahid Jun 13 '20 at 09:39
22

The old tried and true

mkdir /tmp/qq >/dev/null 2>&1

will do what you want with none of the race conditions many of the other solutions have.

Sometimes the simplest (and ugliest) solutions are the best.

paxdiablo
  • 772,407
  • 210
  • 1,477
  • 1,841
  • 6
    This will fail if "tmp" did not exist. nor does it give you any confirmation. – Mike Q Jun 16 '14 at 17:33
  • Race conditions? Can you elaborate in your answer? Non-atomic test & create? – Peter Mortensen Jun 12 '20 at 18:02
  • 1
    @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. – paxdiablo Jun 13 '20 at 03:18
17

mkdir foo works even if the directory exists. To make it work only if the directory named "foo" does not exist, try using the -p flag.

Example:

mkdir -p foo

This will create the directory named "foo" only if it does not exist. :)

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Atul Ranjan
  • 217
  • 3
  • 6
  • 2
    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. – uliwitness Apr 22 '15 at 16:50
14

mkdir does not support -p switch anymore on Windows 8+ systems.

You can use this:

IF NOT EXIST dir_name MKDIR dir_name
Karanvir Kang
  • 1,841
  • 17
  • 16
12
directory_name = "foo"

if [ -d $directory_name ]
then
    echo "Directory already exists"
else
    mkdir $directory_name
fi
WonderWorker
  • 7,388
  • 3
  • 52
  • 71
12

You can either use an if statement to check if the directory exists or not. If it does not exits, then create the directory.

  1. dir=/home/dir_name

    if [ ! -d $dir ]
    then
         mkdir $dir
    else
         echo "Directory exists"
    fi
    
  2. You can directory use mkdir with -p option to create a directory. It will check if the directory is not available it will.

    mkdir -p $dir
    

    mkdir -p also allows to create the tree structure of the directory. If you want to create the parent and child directories using same command, can opt mkdir -p

    mkdir -p /home/parent_dir /home/parent_dir/child1 /home/parent_dir/child2
    
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
AbhinavVaidya8
  • 332
  • 4
  • 17
  • Is there any advantage in using if loop!? why would someone choose that over -p option?! – pedram bashiri Aug 29 '18 at 18:11
  • 1
    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. – AbhinavVaidya8 Sep 02 '18 at 03:19
  • I didn't see a loop. – Amit Naidu Jun 20 '19 at 00:40
10

Referring to man page man mkdir for option -p

   -p, --parents
          no error if existing, make parent directories as needed

which will create all directories in a given path, if exists throws no error otherwise it creates all directories from left to right in the given path. Try the below command. the directories newdir and anotherdir doesn't exists before issuing this command

Correct Usage

mkdir -p /tmp/newdir/anotherdir

After executing the command you can see newdir and anotherdir created under /tmp. You can issue this command as many times you want, the command always have exit(0). Due to this reason most people use this command in shell scripts before using those actual paths.

vkrams
  • 6,227
  • 17
  • 67
  • 113
10

Or if you want to check for existence first:

if [[ ! -e /path/to/newdir ]]; then
            mkdir /path/to/newdir
fi

-e is the exist test for KornShell.

You can also try googling a KornShell manual.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
alkar
  • 5,288
  • 7
  • 25
  • 43
5

This is a simple function (Bash shell) which lets you create a directory if it doesn't exist.

#----------------------------------
# Create a directory if it doesn't exist
#------------------------------------
createDirectory() {
    if [ ! -d $1 ]
        then
        mkdir -p $1
    fi
}

You can call the above function as:

createDirectory /tmp/fooDir/BarDir

The above creates fooDir and BarDir if they don't exist. Note the "-p" option in the mkdir command which creates directories recursively.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
3
mkdir -p sam
  • mkdir = Make Directory
  • -p = --parents
  • (no error if existing, make parent directories as needed)
Draken
  • 3,049
  • 13
  • 32
  • 49
2
if [ !-d $dirName ];then
     if ! mkdir $dirName; then  # Shorter version. Shell will complain if you put braces here though
     echo "Can't make dir: $dirName"
     fi
fi
Alex Zubkov
  • 77
  • 1
  • 1
  • 7
0

Simple, silent and deadly:

mkdir -p /my/new/dir >/dev/null 2>$1
moodboom
  • 4,733
  • 2
  • 35
  • 42