How to Prune Empty Directories in Python with os.walk
Remove all empty subdirectories bottom-up using os.walk with topdown=False and os.rmdir, safely ignoring non-empty folders.
Python code
31 linesimport os
def prune_empty_dirs(root):
"""Remove all empty subdirectories under root, bottom-up."""
for dirpath, dirnames, filenames in os.walk(root, topdown=False):
if dirpath == root:
continue
try:
os.rmdir(dirpath)
print(f"Removed: {dirpath}")
except OSError:
pass # Directory not empty or permission issue
if __name__ == "__main__":
# Create temporary test structure
base = "sample_tree"
os.makedirs(os.path.join(base, "empty1", "nested_empty"), exist_ok=True)
os.makedirs(os.path.join(base, "empty2"), exist_ok=True)
os.makedirs(os.path.join(base, "full", "sub"), exist_ok=True)
with open(os.path.join(base, "full", "sub", "file.txt"), "w") as f:
f.write("keep me")
print("Before pruning:")
for root, dirs, files in os.walk(base):
print(f" {root}")
prune_empty_dirs(base)
print("\nAfter pruning:")
for root, dirs, files in os.walk(base):
print(f" {root}")
Output
Before pruning:
sample_tree
sample_tree/empty1
sample_tree/empty1/nested_empty
sample_tree/empty2
sample_tree/full
sample_tree/full/sub
Removed: sample_tree/empty1/nested_empty
Removed: sample_tree/empty1
Removed: sample_tree/empty2
After pruning:
sample_tree
sample_tree/full
sample_tree/full/sub
How it works
os.walk with topdown=False yields directory paths from deepest to shallowest, so child empty directories are removed before their parents — this lets the parent become empty and get pruned too. os.rmdir only removes empty directories and raises OSError otherwise, which we catch to skip non-empty folders and permission errors. The try/except around os.rmdir makes the pruning safe for directories that contain files or subdirectories that weren't removed.
Common mistakes
- Using topdown=True (default), which prunes parents before children and leaves nested empties behind
- Calling os.remove instead of os.rmdir, which fails with IsADirectoryError on any directory
- Not skipping the root directory, which can cause the base directory itself to be deleted
- Ignoring the exception type and catching all errors silently without logging why a directory wasn't removed
Variations
- Use pathlib.Path.rmdir() inside an rglob loop for a more modern pathlib-based approach
- Add a dry_run flag to print what would be removed without actually deleting anything
Real-world use cases
- Cleaning up temporary build outputs or cache folders before deploying an application
- Removing leftover empty directories after archiving or moving files in a data pipeline
- Maintaining a tidy filesystem for a service that creates nested output folders on each run
Sponsored
More from Files & data
- Append a Line to a Log File in Python easy
- Audit File Permissions Across a Project in Python easy
- Automatically Detect Corrupted Files Using SHA-256 Checksums in Python easy
- Automatically Highlight Data Validation Errors Inside Excel Files in Python easy
- Build a Command-Line To-Do List Application with Data Persistence in Python easy
- Build a File Index by Relative Path Hash Map in Python easy
Keep learning
Related tutorials and quizzes for this topic.