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.")Using pathlib.Path.unlink() (Python 3.4+)
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 send2trashimport 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
| Method | Target | Non-empty dir? | Notes |
|---|---|---|---|
os.remove(path) | Single file | — | Classic, widely supported |
Path.unlink(missing_ok=True) | Single file | — | Modern, race-condition safe |
os.rmdir(path) | Empty directory | No | Raises OSError if not empty |
Path.rmdir() | Empty directory | No | pathlib equivalent |
shutil.rmtree(path) | Directory tree | Yes | Permanent — use with care |
send2trash.send2trash(path) | File or folder | Yes | Recoverable; requires install |
Key Takeaways
- Use
Path.unlink(missing_ok=True)for single-file deletion in modern Python (3.8+). - Use
os.rmdir()orPath.rmdir()for empty directories only. - Use
shutil.rmtree()to remove a directory and all its contents — double-check the path first. - Always handle
FileNotFoundErrorandPermissionErrorto make scripts robust. - Prefer
send2trashwhen a reversible delete is important.
Related Chapters
- Python File Handling — opening, modes, and the
withstatement - Python Read Files — reading data from files
- Python Write / Create Files — writing and creating files
- Python Try Except — handling exceptions robustly