Python
Coding
Programming
Directory Validation
File System

How do I check if a directory exists in Python?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Checking whether a directory exists before reading from it, writing to it, or creating it is a fundamental file system operation in Python. The standard approaches use os.path.isdir() for a simple boolean check and pathlib.Path.is_dir() for a modern, object-oriented approach. Understanding the difference between checking for existence and checking for directories (vs files) prevents subtle bugs.

Method 1: os.path.isdir()

Returns True if the path exists and is a directory:

python
1import os
2
3# Check if directory exists
4if os.path.isdir('/path/to/directory'):
5    print('Directory exists')
6else:
7    print('Directory does not exist')
8
9# Returns False for files, even if they exist
10os.path.isdir('/path/to/file.txt')  # False (it's a file, not a directory)
11
12# Returns False for non-existent paths
13os.path.isdir('/nonexistent/path')  # False

pathlib (Python 3.4+) provides an object-oriented approach:

python
1from pathlib import Path
2
3path = Path('/path/to/directory')
4
5if path.is_dir():
6    print('Directory exists')
7else:
8    print('Directory does not exist')
9
10# Chain with other Path methods
11config_dir = Path.home() / '.config' / 'myapp'
12if not config_dir.is_dir():
13    config_dir.mkdir(parents=True, exist_ok=True)

Method 3: os.path.exists() (Checks Any Path)

os.path.exists() returns True for both files and directories:

python
1import os
2
3# Returns True for directories AND files
4os.path.exists('/path/to/directory')  # True (if exists)
5os.path.exists('/path/to/file.txt')   # True (if exists)
6os.path.exists('/nonexistent')        # False

Use isdir() when you specifically need a directory, and exists() when any path type is acceptable.

Comparison of Methods

MethodChecksReturns True for filesFollows symlinks
os.path.isdir()Directory onlyNoYes
os.path.exists()Any pathYesYes
Path.is_dir()Directory onlyNoYes
Path.exists()Any pathYesYes

Create Directory If Not Exists

python
1import os
2from pathlib import Path
3
4# os.makedirs — create directory and all parents
5os.makedirs('/path/to/new/directory', exist_ok=True)
6# exist_ok=True prevents error if directory already exists
7
8# pathlib equivalent
9Path('/path/to/new/directory').mkdir(parents=True, exist_ok=True)
10
11# Without exist_ok, raises FileExistsError if directory exists
12try:
13    os.makedirs('/existing/directory')
14except FileExistsError:
15    print('Directory already exists')

Checking Permissions

A directory may exist but not be readable or writable:

python
1import os
2
3path = '/path/to/directory'
4
5if os.path.isdir(path):
6    if os.access(path, os.R_OK):
7        print('Directory is readable')
8    if os.access(path, os.W_OK):
9        print('Directory is writable')
10    if os.access(path, os.X_OK):
11        print('Directory is accessible (can list contents)')

By default, both isdir() and is_dir() follow symbolic links:

python
1import os
2from pathlib import Path
3
4# If /tmp/link is a symlink pointing to a directory
5os.path.isdir('/tmp/link')      # True — follows the symlink
6os.path.islink('/tmp/link')     # True — it IS a symlink
7
8# Check if it's a symlink to a directory
9path = Path('/tmp/link')
10if path.is_symlink() and path.is_dir():
11    print('Symlink pointing to a directory')
12
13# Check the symlink target without following
14if path.is_symlink():
15    target = path.resolve()
16    print(f'Links to: {target}')

EAFP vs LBYL

Python encourages "Easier to Ask Forgiveness than Permission" (EAFP) over "Look Before You Leap" (LBYL). Instead of checking existence first, try the operation and catch the exception:

python
1# LBYL (check first) — race condition possible
2if os.path.isdir(path):
3    files = os.listdir(path)  # Directory could be deleted between check and use
4
5# EAFP (try first) — no race condition
6try:
7    files = os.listdir(path)
8except FileNotFoundError:
9    print('Directory does not exist')
10except PermissionError:
11    print('No permission to read directory')

EAFP is preferred when multiple processes or threads might modify the filesystem concurrently.

Common Pitfalls

  • os.path.exists() returns True for files too: If you need to verify something is specifically a directory (not a file), use isdir() instead of exists(). exists() returns True for both.
  • Race conditions (TOCTOU): Between checking isdir() and using the directory, another process can delete it. Use EAFP with try/except for robust code.
  • Relative paths: os.path.isdir('data') checks relative to the current working directory, which may differ from where your script is located. Use Path(__file__).parent / 'data' for paths relative to the script.
  • Trailing slashes: os.path.isdir('/path/to/file/') returns False even if /path/to/file exists as a file. The trailing slash does not make it a directory check — it just means the path lookup fails.
  • Broken symlinks: isdir() returns False for broken symlinks (where the target does not exist). Use os.path.islink() to check for the symlink itself.

Summary

  • Use os.path.isdir(path) to check if a path is an existing directory
  • Use Path(path).is_dir() for the modern pathlib approach
  • Use os.makedirs(path, exist_ok=True) to create a directory (with parents) only if it does not exist
  • Prefer EAFP (try/except) over LBYL (check-then-act) to avoid race conditions
  • Use isdir() instead of exists() when you specifically need a directory, not just any existing path

Course illustration
Course illustration

All Rights Reserved.