W3docs

Python Delete Files and Directories

Learn how to delete files and directories in Python using os.remove, pathlib.Path.unlink, os.rmdir, and shutil.rmtree with safe error handling.

This chapter covers every standard way to delete files and directories in Python — from the classic os module to the modern pathlib API and the shutil module for non-empty directories. You will also learn safe patterns for error handling so that your code degrades gracefully when a file is already gone or a permission is denied.

Deleting a Single File

Using os.remove()

The os module is part of Python's standard library and provides a portable interface to operating-system functions. os.remove() deletes a single file. It raises FileNotFoundError if the path does not exist and PermissionError if the process lacks the required permissions.

Delete a file with os.remove()

import os

os.remove("report.txt")

Wrap the call in a try/except block so your program handles missing files gracefully:

Delete a file with error handling

import os

try:
    os.remove("report.txt")
    print("File deleted.")
except FileNotFoundError:
    print("File not found — nothing to delete.")
except PermissionError:
    print("Permission denied.")

pathlib provides an object-oriented interface for filesystem paths. Path.unlink() deletes the file the path points to. Since Python 3.8 you can pass missing_ok=True to suppress FileNotFoundError automatically.

Delete a file with pathlib

from pathlib import Path

# Raises FileNotFoundError if the file does not exist
Path("report.txt").unlink()

Delete a file silently if it does not exist (Python 3.8+)

from pathlib import Path

Path("report.txt").unlink(missing_ok=True)
print("Done — file deleted or was already absent.")

missing_ok=True is the idiomatic Python 3.8+ alternative to a check-then-delete pattern. Prefer it over os.path.exists() checks because it avoids a race condition: another process could delete the file between your check and your delete call.

Checking existence before deleting (classic pattern)

Before missing_ok was added, the standard approach was an os.path.exists() guard:

Check existence before deleting

import os

if os.path.exists("report.txt"):
    os.remove("report.txt")
else:
    print("File not found.")

This works fine for scripts where race conditions are not a concern, but missing_ok=True is cleaner in new code.

Deleting an Empty Directory

os.rmdir() removes a directory, but only if it is empty. It raises OSError if the directory contains any files or subdirectories.

Delete an empty directory

import os

try:
    os.rmdir("empty_folder")
    print("Directory removed.")
except FileNotFoundError:
    print("Directory not found.")
except OSError:
    print("Directory is not empty or cannot be removed.")

With pathlib, use Path.rmdir():

from pathlib import Path

Path("empty_folder").rmdir()

Deleting a Non-Empty Directory

To remove a directory and everything inside it (files, subdirectories, and their contents), use shutil.rmtree(). This is the equivalent of rm -rf on Unix — it is permanent and irreversible.

Delete a directory tree

import shutil

shutil.rmtree("old_project")
print("Directory and all its contents deleted.")

Add error handling for the common failure modes:

Delete a directory tree safely

import shutil

try:
    shutil.rmtree("old_project")
    print("Deleted successfully.")
except FileNotFoundError:
    print("Directory not found.")
except PermissionError:
    print("Permission denied.")

The ignore_errors parameter

Pass ignore_errors=True to suppress all errors silently. Use this only when you genuinely do not care whether the deletion succeeded:

import shutil

shutil.rmtree("old_project", ignore_errors=True)

Deleting Multiple Files Matching a Pattern

To delete all files matching a glob pattern, combine pathlib.Path.glob() with unlink():

Delete all .log files in a directory

from pathlib import Path

deleted = 0
for log_file in Path(".").glob("*.log"):
    log_file.unlink()
    deleted += 1
print(f"{deleted} log file(s) deleted.")

To search subdirectories recursively, use rglob():

Delete all .tmp files in a directory tree

from pathlib import Path

for tmp_file in Path(".").rglob("*.tmp"):
    tmp_file.unlink(missing_ok=True)

The os module equivalent uses os.listdir() and os.remove():

Delete all .txt files using os

import os

directory = "."
for filename in os.listdir(directory):
    if filename.endswith(".txt"):
        os.remove(os.path.join(directory, filename))

Always review which files match before running a bulk deletion. A quick print() pass before the delete loop is a safe habit.

Sending Files to the Recycle Bin (Reversible Delete)

os.remove() and Path.unlink() delete files permanently — there is no undo. If you need a recoverable delete (sending a file to the system Trash/Recycle Bin), install the third-party send2trash package:

pip install send2trash
import send2trash

send2trash.send2trash("report.txt")
print("File moved to Trash.")

This is useful in desktop tools or scripts where accidental deletion would be catastrophic.

Comparison of Deletion Methods

MethodTargetNon-empty dir?Notes
os.remove(path)Single fileClassic, widely supported
Path.unlink(missing_ok=True)Single fileModern, race-condition safe
os.rmdir(path)Empty directoryNoRaises OSError if not empty
Path.rmdir()Empty directoryNopathlib equivalent
shutil.rmtree(path)Directory treeYesPermanent — use with care
send2trash.send2trash(path)File or folderYesRecoverable; requires install

Key Takeaways

  • Use Path.unlink(missing_ok=True) for single-file deletion in modern Python (3.8+).
  • Use os.rmdir() or Path.rmdir() for empty directories only.
  • Use shutil.rmtree() to remove a directory and all its contents — double-check the path first.
  • Always handle FileNotFoundError and PermissionError to make scripts robust.
  • Prefer send2trash when a reversible delete is important.
Was this page helpful?