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.

Easy Python 3.9+ Aug 9, 2026 Files & data 15 views 0 copies

Python code

31 lines
Python 3.9+
import 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

stdout
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

  1. Use pathlib.Path.rmdir() inside an rglob loop for a more modern pathlib-based approach
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Files & data

Related tutorials and quizzes for this topic.