Path.mkdir

p.mkdir(parents=True, exist_ok=True) is the 'make sure this folder exists' idiom — it is os.makedirs(p, exist_ok=True). touch, unlink and rmdir cover the rest of the create/delete basics; for non-empty folders use shutil.rmtree.

pathlib methodPython 3.4+ (exist_ok 3.5+, missing_ok 3.8+)Live demo
Common call
out.mkdir(parents=True, exist_ok=True)
Returns
None
Replaces
os.makedirs(out, exist_ok=True) / os.remove / os.rmdir
Watch out
rmdir only removes EMPTY folders; unlink refuses folders
Path.mkdir(modemode — Permission bits, combined with the process umask (POSIX).type: int · default: 0o777 / 0o666=0o777, parentsparents — mkdir: also create missing parent folders (they get the default mode).type: bool · default: False=False, exist_okexist_ok — mkdir (default False): no error if the folder already exists. touch (default True): no error if the file exists — it just updates the modification time.type: bool · default: False / True=False) / .touch(mode=0o666, exist_okexist_ok — mkdir (default False): no error if the folder already exists. touch (default True): no error if the file exists — it just updates the modification time.type: bool · default: False / True=True) / .unlink(missing_ok=False) / .rmdir()
→ None

Demo

Live evaluation
The idiom runs twice here without an error, and creates every missing level.
Try:
Inputs
pathstrfolder to create
Code
from pathlib import Path
p = Path('build/reports/2026')
p.mkdir(parents=True, exist_ok=True)
p.mkdir(parents=True, exist_ok=True)
(p.is_dir(), sorted(q.as_posix() for q in Path('.').rglob('*')))
Result
(True, ['build', 'build/reports', 'build/reports/2026'])

With parents=True every missing level is created, and exist_ok=True turns the second call into a no-op — so the idiom is safe to run on every start-up. Path('.') always exists, so mkdir(exist_ok=True) on it does nothing. The plain tab shows the error types only, because their messages differ by OS ([Errno 17] on Linux, [WinError 183] on Windows for the same FileExistsError).

Parameters

NameTypeRequiredDescription
parentsboolno (False)mkdir: also create missing parent folders (they get the default mode).
exist_okboolno (False / True)mkdir (default False): no error if the folder already exists. touch (default True): no error if the file exists — it just updates the modification time.
modeintno (0o777 / 0o666)Permission bits, combined with the process umask (POSIX).
missing_okboolno (False)unlink (3.8+): no error if the file does not exist.

Return value

None — All four act on the file system and return None.

Common patterns

Ensure the parent folder of an output file
Create the folder, then write the file.
from pathlib import Path
out = Path('reports/2026/q3.csv')
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(csv_text, encoding='utf-8')
Delete a file if it is there
missing_ok=True replaces exists() + unlink(), without the race.
from pathlib import Path
Path('app.pid').unlink(missing_ok=True)
Remove a non-empty folder
rmdir refuses; shutil.rmtree deletes the whole tree.
import shutil
from pathlib import Path
shutil.rmtree(Path('build'), ignore_errors=True)
Create a marker file only once
touch(exist_ok=False) fails if another process created it first.
from pathlib import Path
try:
    Path('setup.done').touch(exist_ok=False)
except FileExistsError:
    print('already set up')

Examples

1. Create nested folders
from pathlib import Path Path('a/b/c').mkdir(parents=True) Path('a/b/c').is_dir()
Returns
True
2. Idempotent with exist_ok
from pathlib import Path for _ in range(2): Path('cache').mkdir(exist_ok=True) Path('cache').is_dir()
Returns
True
3. touch creates an empty file
from pathlib import Path p = Path('empty.txt') p.touch() (p.is_file(), p.stat().st_size)
Returns
(True, 0)
4. touch(exist_ok=False) on an existing file
from pathlib import Path Path('lock').touch() Path('lock').touch(exist_ok=False)
Returns
FileExistsError: [Errno 17] File exists: 'lock'
5. unlink deletes a file
from pathlib import Path p = Path('old.log') p.touch() p.unlink() p.exists()
Returns
False
6. unlink(missing_ok=True)
from pathlib import Path Path('never-existed.txt').unlink(missing_ok=True) 'no error'
Returns
'no error'
7. rmdir refuses non-empty folders
from pathlib import Path Path('full').mkdir() Path('full/x').touch() try: Path('full').rmdir() except OSError as e: result = type(e).__name__ result
Returns
'OSError'

Pitfalls

1. mkdir() without exist_ok in re-runnable code
The second run fails because the folder is already there.
plain mkdir
from pathlib import Path
Path('out').mkdir()
try:
    Path('out').mkdir()
except OSError as e:
    result = type(e).__name__
result
'FileExistsError'
exist_ok=True
from pathlib import Path
Path('out').mkdir()
Path('out').mkdir(exist_ok=True)
Path('out').is_dir()
True
2. exist_ok=True when a FILE has that name
exist_ok only forgives an existing directory. A file in the way still raises FileExistsError.
file in the way
from pathlib import Path
Path('data').touch()
try:
    Path('data').mkdir(exist_ok=True)
except OSError as e:
    result = type(e).__name__
result
'FileExistsError'
check first
from pathlib import Path
Path('data').touch()
p = Path('data')
'use another name' if p.exists() and not p.is_dir() else p.mkdir(exist_ok=True)
'use another name'
3. Checking exists() before unlink()
Between the check and the delete another process may remove the file. missing_ok=True does both atomically.
check then delete
from pathlib import Path
p = Path('tmp.lock')
if p.exists():
    p.unlink()
p.exists()
False
missing_ok=True
from pathlib import Path
p = Path('tmp.lock')
p.unlink(missing_ok=True)
p.exists()
False

When to use

Use it
  • Making output folders (mkdir(parents=True, exist_ok=True))
  • Creating empty marker files (touch) and removing files (unlink)
  • Removing folders you have emptied (rmdir)
Reach for something else
  • Deleting a folder with content → shutil.rmtree
  • Temporary folders → tempfile.TemporaryDirectory

Notes

CPython impl
Lib/pathlib/_local.py: mkdir calls os.mkdir; on FileNotFoundError with parents=True it creates self.parent recursively and retries; any other OSError is re-raised unless exist_ok and the path is a directory
Messages differ by OS
FileExistsError reads '[Errno 17] File exists' on Linux but '[WinError 183] Cannot create a file when that file already exists' on Windows for mkdir; touch(exist_ok=False) goes through os.open and reads '[Errno 17] File exists' on both
unlink on a folder
Raises an OSError subclass that depends on the OS (PermissionError on Windows) — use rmdir()
rmdir non-empty
OSError on every OS; on Windows the message is '[WinError 145] The directory is not empty'

FAQ

Path('folder').mkdir(parents=True, exist_ok=True). parents creates missing parent folders, exist_ok skips the error if it is already there.