Is there any way to remove a directory and it’s contents in the PathLib module? With path.unlink() it only removes a file, with path.rmdir() the directory has to be empty. Is there no way to do it in one function call?
7 Answers
As you already know, the only two Path methods for removing files/directories are .unlink() and .rmdir() and neither does what you want.
Pathlib is a module that provides object oriented paths across different OS's, it isn't meant to have lots of diverse methods.
The aim of this library is to provide a simple hierarchy of classes to handle filesystem paths and the common operations users do over them.
The "uncommon" file system alterations, such as recursively removing a directory, is stored in different modules. If you want to recursively remove a directory, you should use the shutil module. (It works with Path instances too!)
import shutil
import pathlib
import os # for checking results
print(os.listdir())
# ["a_directory", "foo.py", ...]
path = pathlib.Path("a_directory")
shutil.rmtree(path)
print(os.listdir())
# ["foo.py", ...]
-
3just for mention, can be done this way -https://stackoverflow.com/a/49782093/4249707 – El Ruso Nov 07 '18 at 22:44
-
94I still don’t get, why a recursive version is not part of pathlib.Path, when everything, what is needed is already there. I was really hoping, this confusing usage of os.path, os.mkdir, shutil, etc. would end with pathlib. – Sebastian Werk Apr 09 '19 at 09:29
-
2@SebastianWerk PR! PR! PR! -- although being in the stdlibrary it won't be out for a while sadly and would take a lot of effort to get in. I share your sentiments – SwimBikeRun Jul 12 '19 at 00:33
Here's a pure pathlib implementation:
from pathlib import Path
def rm_tree(pth):
pth = Path(pth)
for child in pth.glob('*'):
if child.is_file():
child.unlink()
else:
rm_tree(child)
pth.rmdir()
- 357
- 2
- 2
-
4This would delete the contents of symlinked directories, I'd have thought? – user2846495 Jul 22 '21 at 13:30
-
1The unsafe version of `shutil.rmtree` does something similar ([source](https://github.com/python/cpython/blob/0ac5372bf6b937ed44a8f9c4e402d024fcd80870/Lib/shutil.py#L595)), but it raises an `OSError("Cannot call rmtree on a symbolic link")` in case of symlinked dir. – djvg Feb 11 '22 at 13:24
Otherwise, you can try this one if you want only pathlib:
from pathlib import Path
def rm_tree(pth: Path):
for child in pth.iterdir():
if child.is_file():
child.unlink()
else:
rm_tree(child)
pth.rmdir()
rm_tree(your_path)
- 192
- 1
- 7
-
-
Is it safe to mutate the dir you're iterating over? Might have to extract the full results of the `iterdir()` to a list before starting to iterate. – Roger Dahl Jun 17 '21 at 06:26
-
The recursive function will continue removing files (child.unlink()) until the directory is empty. Once empty, the directory is removed (pth.rmdir()). – Rami Jun 21 '21 at 19:32
If you don't mind using a third-party library give path a try.
Its API is similar to pathlib.Path, but provides some additional methods, including Path.rmtree() to recursively delete a directory tree.
- 6,987
- 4
- 53
- 56
You might use pathlib3x - it offers a backport of the latest (at the date of writing this answer Python 3.10.a0) Python pathlib for Python 3.6 or newer, and a few additional functions like rmtree
>>> python -m pip install pathlib3x
>>> import pathlib3x as pathlib
>>> my_path = pathlib.Path('c:/tmp/some_directory')
>>> my_path.rmtree(ignore_errors=True)
you can find it on github or PyPi
Disclaimer: I'm the author of the pathlib3x library.
- 1,308
- 7
- 17
Simple and effective:
def rmtree(f: Path):
if f.is_file():
f.unlink()
else:
for child in f.iterdir():
rmtree(child)
f.rmdir()
- 107
- 12