74

Here are four paths:

p1=r'\foo\bar\foobar.txt'
p2=r'\foo\bar\foo\foo\foobar.txt'
p3=r'\foo\bar\foo\foo2\foobar.txt'
p4=r'\foo2\bar\foo\foo\foobar.txt'

The directories may or may not exist on a drive. What would be the most elegant way to create the directories in each path?

I was thinking about using os.path.split() in a loop, and checking for a dir with os.path.exists, but I don't know it there's a better approach.

marw
  • 2,939
  • 4
  • 28
  • 37

3 Answers3

95

You are looking for os.makedirs() which does exactly what you need.

The documentation states:

Recursive directory creation function. Like mkdir(), but makes all intermediate-level directories needed to contain the leaf directory. Raises an error exception if the leaf directory already exists or cannot be created.

By default it fails if the leaf directory already exists; you'll want to test for existence before calling os.makedirs() or use os.makedirs(..., exist_ok=True) to ignore existence.

greybeard
  • 2,249
  • 8
  • 30
  • 66
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 2
    Lol. 1:0 for Python. Can't believe I've missed that and that I've been using `os.mkdir()` exclusively. Thanks, David :) – marw Mar 06 '11 at 13:38
  • @marw I'd never heard of it either, I just did a websearch with the magic key word "recursive"! – David Heffernan Mar 06 '11 at 13:39
  • 2
    testing on existence introduces possible race condition (the directory might be created *after* you tested its existance by *before* your call to `makedirs()`). So just use `try: .. except OSError` without the test. – jfs Mar 08 '11 at 21:01
  • @J.F. Well, that doesn't really help much because the operation to make the directories is not atomic anyway. Race issues are unavoidable unless you have a proper transactional filesystem. – David Heffernan Mar 08 '11 at 21:17
  • 14
    @David Heffernan: You're right it won't solve all problems e.g., world hunger. One step at a time. btw, if you don't like `try: except`; use `exist_ok=True`. – jfs Mar 08 '11 at 21:56
  • 1
    @J.F. exist_ok is neat, I didn't see it since it seems to be very new - I was looking at 2.7 docs. Thanks! – David Heffernan Mar 08 '11 at 22:04
  • @jfs Nice! I wish your comment were highlighted in the answer because I missed it a few times ago when I looked at this topic. – Linh Jun 01 '18 at 20:58
  • *equivalent of* `mkdir -p` – Scrooge McDuck Oct 31 '21 at 20:26
56

On Python 3.6+ you can do:

import pathlib

path = pathlib.Path(p4)
path.parent.mkdir(parents=True, exist_ok=True)
axwell
  • 677
  • 5
  • 6
2

A simple way to build the paths in POSIX systems. Assume your path is something like: dirPath = '../foo/bar', where neither foo or bar exist:

path = ''
for d in dirPath.split('/'):
   # handle instances of // in string
   if not d: continue 

   path += d + '/'
   if not os.path.isdir(path):
      os.mkdir(path)
   
RexBarker
  • 1,456
  • 16
  • 14