Delete a File/Directory in Python: os.remove, shutil.rmtree
In Python, os.remove()
allows you to delete (remove) a file, and shutil.rmtree()
allows you to delete a directory (folder) along with all its files and subdirectories. You can also use os.rmdir()
and os.removedirs()
to remove only empty directories.
Please note that in all cases, files or directories are permanently deleted and will not be moved to the trash.
If you want to move or copy files and directories to a different location, you can use os.shutil.move()
and os.shutil.copy()
.
- Move a file/directory in Python (shutil.move)
- Copy a file/directory in Python (shutil.copy, shutil.copytree)
The sample code in this article imports the os and shutil modules as shown below. Both are part of the standard library, so no additional installation is necessary.
import os
import shutil
Delete a file with os.remove()
os.remove()
allows you to delete a file.
Specify the file's path (either as a path string or a path-like object such as pathlib.Path
), and it will be deleted.
os.remove('temp/file.txt')
Note that os.remove()
can only delete files. Attempting to delete a directory will cause an error.
# os.remove('temp/')
# PermissionError: [Errno 1] Operation not permitted: 'temp/'
To delete a directory, use shutil.rmtree()
, os.rmdir()
, and os.removedirs()
, which are explained below.
Delete a directory and its contents with shutil.rmtree()
shutil.rmtree()
allows you to delete a directory and all of its files and subdirectories.
shutil.rmtree()
only accepts paths pointing to directories. Providing a file's path will result in an error.
# shutil.rmtree('temp/dir/file.txt')
# NotADirectoryError: [Errno 20] Not a directory: 'temp/dir/file.txt'
If a directory path is specified, all files and subdirectories in the directory are deleted recursively. When specifying a directory, the trailing delimiter (/
) may be present or absent.
shutil.rmtree('temp/dir/')
Empty a directory
If you want to empty a directory, simply delete everything with shutil.rmtree()
and create a new directory with the same name using os.mkdir()
.
target_dir = 'temp'
shutil.rmtree(target_dir)
os.mkdir(target_dir)
Delete an empty directory with os.rmdir()
and os.removedirs()
There are also os.rmdir()
and os.removedirs()
that only delete empty directories.
os.rmdir()
os.rmdir()
deletes a single empty directory.
os.rmdir('temp/dir_empty/')
An error will occur if the directory is not empty, meaning it contains files or subdirectories.
# os.rmdir('temp/dir_not_empty/')
# OSError: [Errno 66] Directory not empty: 'temp/dir_not_empty/'
You can use exception handling to safely delete only empty directories without causing errors for non-empty ones. In the following example, if the directory isn't empty, the program simply skips it using the pass
statement.
try:
os.rmdir('temp/dir_not_empty/')
except OSError as e:
pass
To delete the contents all together, use shutil.rmtree()
as described above.
shutil.rmtree('temp/dir_not_empty/')
os.removedirs()
os.removedirs()
deletes empty directories recursively.
If an empty directory is specified, any parent directories that are also empty will be removed in order.
For example,
os.removedirs('foo/bar/baz')
will first remove the directory'foo/bar/baz'
, and then remove'foo/bar'
and'foo'
if they are empty. os.removedirs() — Miscellaneous operating system interfaces — Python 3.11.4 documentation
Consider the following files and directories:
temp/
└── dir1/
├── dir2/
│ └── dir3/
└── file.txt
Specify an empty directory at the end.
os.removedirs('temp/dir1/dir2/dir3')
The result is as follows: dir3
is deleted because it's empty. After dir3
is removed, dir2 becomes empty and is then deleted. dir1
is not deleted because it is not empty.
temp/
└── dir1/
└── file.txt
Delete multiple files based on certain conditions with wildcards and regex
As a practical use case for os.remove()
, let's see how to delete multiple files based on certain conditions.
Please note that using **
in glob.glob()
can be time-consuming when dealing with a large number of files and directories. If feasible, consider using conditions with other special characters for improved efficiency.
Use wildcards to specify conditions
The glob
module allows you to use wildcard characters like *
to generate a list of files and directories. For detailed usage, refer to the following article.
Consider the following files and directories:
temp/
├── 123.jpg
├── 456.txt
├── abc.txt
└── dir/
├── 000.csv
├── 789.txt
└── xyz.jpg
You can extract and delete txt
files, including those in subdirectories.
import os
import glob
for p in glob.glob('temp/**/*.txt', recursive=True):
if os.path.isfile(p):
os.remove(p)
Here's the result.
temp/
├── 123.jpg
└── dir/
├── 000.csv
└── xyz.jpg
In the above example, there's no problem. However, under different conditions, directories might be included in the results. Therefore, os.path.isfile()
is used to target only files.
If you want to delete directories, use os.path.isdir()
and shutil.rmtree()
instead of os.path.isfile()
and os.remove()
.
Use regex to specify conditions
For complex conditions that can't be handled by glob alone, use the re
module to specify conditions with regular expressions.
Consider the following files and directories:
temp/
├── 123.jpg
├── 456.txt
├── abc.txt
└── dir/
├── 000.csv
├── 789.txt
└── xyz.jpg
Use glob.glob()
with **
and recursive=True
to recursively list all files and directories, and then filter them by regex with re.search()
.
For example, to extract and delete files with names consisting only of digits and either a txt
or csv
extension, including files in subdirectories, use \d
to match digits, +
to match one or more repetitions, and (a|b)
to match either a
or b
.
import os
import glob
import re
for p in glob.glob('temp/**', recursive=True):
if os.path.isfile(p) and re.search('\d+\.(txt|csv)', p):
os.remove(p)
Here's the result.
temp/
├── 123.jpg
├── abc.txt
└── dir/
└── xyz.jpg