Delete Files and Directories in Python: os, pathlib, and shutil

Scripts that create temporary files, logs, or build artifacts usually need to clean up after themselves. You may need to remove a single file, all files that match a pattern, or an entire directory tree.
Python does not have one function that does all of this. The os, pathlib, and shutil modules each cover a different part of the job.
This article explains how to use os.remove(), pathlib.Path.unlink(), and shutil.rmtree() to remove files and directories, including pattern-based deletion and recursive directory removal.
Deleting Files
In Python you can use os.remove(), os.unlink(), pathlib.Path.unlink() to delete a single file.
The os
module provides a portable way of interacting with the operating system.
To delete a single file with os.remove(), pass the path to the file as an argument:
import os
file_path = '/tmp/file.txt'
os.remove(file_path)os.remove() and os.unlink() functions are semantically identical:
import os
file_path = '/tmp/file.txt'
os.unlink(file_path)If the specified file does not exist
, Python raises a FileNotFoundError exception. Both os.remove() and os.unlink() can delete only files, not directories. If the given path points to a directory, Python raises an OSError; the specific subclass depends on the operating system.
Deleting a file requires write and execute permission on the directory containing the file. Otherwise, you will get a PermissionError.
To avoid errors when deleting files, you can use exception handling to catch the exception and send a proper error message:
import os
file_path = '/tmp/file.txt'
try:
os.remove(file_path)
except OSError as e:
print("Error: %s : %s" % (file_path, e.strerror))The pathlib
module provides an object-oriented interface for working with filesystem paths. It is available in Python 3.4 and above.
To delete a file with the pathlib module, create a Path object pointing to the file and call the unlink() method on the object:
from pathlib import Path
file_path = Path('/tmp/file.txt')
try:
file_path.unlink()
except OSError as e:
print("Error: %s : %s" % (file_path, e.strerror))In Python 3.8 and above, you can pass missing_ok=True to suppress the FileNotFoundError if the file does not exist:
from pathlib import Path
Path('/tmp/file.txt').unlink(missing_ok=True)pathlib.Path.unlink(), os.remove(), and os.unlink() can also be used to delete a symlink
.
Delete a File If It Exists
A common requirement is to delete a file only when it is present, without raising an error if it is not. If you are using Python 3.8 or newer, Path.unlink(missing_ok=True) is the simplest option, shown above.
For os.remove(), prefer catching FileNotFoundError instead of checking first. This avoids a race where another process deletes the file after the check but before os.remove() runs:
import os
file_path = '/tmp/file.txt'
try:
os.remove(file_path)
except FileNotFoundError:
passYou may also see examples that check the path first with os.path.exists()
:
import os
file_path = '/tmp/file.txt'
if os.path.exists(file_path):
os.remove(file_path)This is fine for simple scripts, but it is not as safe as handling FileNotFoundError. It also returns False for broken symlinks; use os.path.lexists() if you need to detect and remove broken symlinks.
Delete Files by Pattern
You can use the glob
module to match multiple files based on a pattern. For example, to remove all .txt files in the /tmp directory, you would use something like this:
import os
import glob
files = glob.glob('/tmp/*.txt')
for f in files:
try:
os.remove(f)
except OSError as e:
print("Error: %s : %s" % (f, e.strerror))To recursively delete all .txt files in the /tmp directory and all subdirectories under it, pass the recursive=True argument to the glob() function and use the ** pattern:
import os
import glob
files = glob.glob('/tmp/**/*.txt', recursive=True)
for f in files:
try:
os.remove(f)
except OSError as e:
print("Error: %s : %s" % (f, e.strerror))The pathlib module includes two glob methods, glob() and rglob(), for matching paths in a directory. glob() follows the relative pattern you provide, including nested and recursive patterns. rglob() searches recursively without requiring the **/ prefix. The following example deletes all .txt files in the top level of the /tmp directory:
from pathlib import Path
for f in Path('/tmp').glob('*.txt'):
try:
f.unlink()
except OSError as e:
print("Error: %s : %s" % (f, e.strerror))Delete All Files in a Directory
Sometimes you need to empty a directory but keep the directory itself. For example, you may want to clear a cache or an upload folder before each run of a script.
unlink() do not go to the trash. Print the list of paths first and check it before you delete anything.To see which entries are in the directory, loop over it with iterdir() and print each path:
from pathlib import Path
for f in Path('/tmp/data').iterdir():
print(f)The iterdir() method returns every entry in the directory, including hidden files and subdirectories. The following code deletes the files and symlinks and leaves the subdirectories in place:
from pathlib import Path
for f in Path('/tmp/data').iterdir():
if f.is_file() or f.is_symlink():
f.unlink()The is_file() method follows symlinks and returns False when the link target is missing. The is_symlink() check catches those broken links. A symlink to a directory is removed as a link, and the directory it points to is not touched.
To delete the files in all subdirectories too, replace iterdir() with rglob('*'). The actual directories stay in place, while files and symlinks are removed:
from pathlib import Path
for f in Path('/tmp/data').rglob('*'):
if f.is_file() or f.is_symlink():
f.unlink()You may also see code that removes the whole directory with shutil.rmtree() and then creates it again with os.mkdir(). It is shorter, but it deletes the subdirectories as well. The new directory also gets default permissions and belongs to the user who runs the script, not to the original owner.
Deleting Directories (Folders)
In Python you can use os.rmdir() and pathlib.Path.rmdir() to delete an empty directory and shutil.rmtree() to delete a non-empty directory.
The following example shows how to remove an empty directory:
import os
dir_path = '/tmp/img'
try:
os.rmdir(dir_path)
except OSError as e:
print("Error: %s : %s" % (dir_path, e.strerror))Alternatively, you can delete directories with the pathlib module:
from pathlib import Path
dir_path = Path('/tmp/img')
try:
dir_path.rmdir()
except OSError as e:
print("Error: %s : %s" % (dir_path, e.strerror))The shutil
module allows you to perform a number of high-level operations on files and directories.
shutil.rmtree() because it removes the directory and everything under it recursively. Double-check the path before you run it, especially when the path comes from a variable or user input.With the shutil.rmtree() function you can delete a given directory including its content:
import shutil
dir_path = '/tmp/img'
try:
shutil.rmtree(dir_path)
except OSError as e:
print("Error: %s : %s" % (dir_path, e.strerror))The argument passed to shutil.rmtree() cannot be a symbolic link to a directory.
To silently ignore any errors during deletion, pass ignore_errors=True:
import shutil
shutil.rmtree('/tmp/img', ignore_errors=True)The pathlib module does not have a method for removing a non-empty directory. Path.rmdir() works only on empty directories. To delete a directory tree, pass the Path object to shutil.rmtree():
import shutil
from pathlib import Path
shutil.rmtree(Path('/tmp/img'))Quick Reference
For a printable quick reference, see the Python cheatsheet .
| Task | Function |
|---|---|
| Delete a file | os.remove(path) or Path(path).unlink() |
| Delete a file (no error if missing) | Path(path).unlink(missing_ok=True) |
| Delete a symlink | os.remove(path) or Path(path).unlink() |
| Delete an empty directory | os.rmdir(path) or Path(path).rmdir() |
| Delete a directory and its contents | shutil.rmtree(path) |
| Delete a directory, ignore errors | shutil.rmtree(path, ignore_errors=True) |
| Delete files by pattern | glob.glob(pattern) + os.remove() |
| Delete files recursively by pattern | glob.glob('**/*.ext', recursive=True) + os.remove() |
| Delete files with pathlib glob | Path(dir).glob('*.ext') + .unlink() |
| Delete files recursively with pathlib | Path(dir).rglob('*.ext') + .unlink() |
| Delete all files in a directory | Path(dir).iterdir() + .unlink() on files |
FAQ
What is the difference between os.remove() and os.unlink()?
They are semantically identical. unlink is the traditional Unix name for the operation. Both delete a single file and raise FileNotFoundError if the path does not exist.
How do I delete a directory and all its contents?
Use shutil.rmtree(path). To suppress errors, pass ignore_errors=True. Note that os.rmdir() only works on empty directories.
Can I use pathlib to delete files matching a pattern?
Yes. Use Path(directory).glob('*.txt') to match files and call .unlink() on each result. For recursive matches, use .rglob('*.txt') instead.
Conclusion
Use os.remove() or Path.unlink() for single files, Path.rmdir() for empty directories, and shutil.rmtree() for a whole directory tree. When a script deletes a file only if it is present, see our guide on how to check if a file exists in Python
.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page