What is the easiest way to do the equivalent of rm -rf
in Python?

- 63,369
- 21
- 118
- 128

- 21,808
- 28
- 67
- 63
-
1Possible duplicate of [How do I remove/delete a folder that is not empty with Python?](http://stackoverflow.com/questions/303200/how-do-i-remove-delete-a-folder-that-is-not-empty-with-python) – Trevor Boyd Smith Nov 04 '16 at 19:23
8 Answers
import shutil
shutil.rmtree("dir-you-want-to-remove")

- 951,095
- 183
- 1,149
- 1,285

- 21,808
- 28
- 67
- 63
-
26While useful, rmtree isn't equivalent: it errors out if you try to remove a single file. – Gabriel Grant Mar 04 '12 at 23:28
-
For a more generic "remove non-empty directory" question where this answer would be a better fit see: http://stackoverflow.com/questions/303200/how-do-i-remove-delete-a-folder-that-is-not-empty-with-python – Ciro Santilli OurBigBook.com Dec 19 '14 at 07:41
-
`rm -rf non-existing-folder` works fine (it doesn't do anything), but your script will fail – Eric Duminil Nov 17 '19 at 21:22
While useful, rmtree isn't equivalent: it errors out if you try to remove a single file, which rm -f
does not (see example below).
To get around this, you'll need to check whether your path is a file or a directory, and act accordingly. Something like this should do the trick:
import os
import shutil
def rm_r(path):
if os.path.isdir(path) and not os.path.islink(path):
shutil.rmtree(path)
elif os.path.exists(path):
os.remove(path)
Note: this function will not handle character or block devices (that would require using the stat
module).
Example in difference of between rm -f
and Python's shutils.rmtree
$ mkdir rmtest
$ cd rmtest/
$ echo "stuff" > myfile
$ ls
myfile
$ rm -rf myfile
$ ls
$ echo "stuff" > myfile
$ ls
myfile
$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import shutil
>>> shutil.rmtree('myfile')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/shutil.py", line 236, in rmtree
onerror(os.listdir, path, sys.exc_info())
File "/usr/lib/python2.7/shutil.py", line 234, in rmtree
names = os.listdir(path)
OSError: [Errno 20] Not a directory: 'myfile'
Edit: handle symlinks; note limitations as per @pevik's comment

- 5,415
- 2
- 32
- 40
-
2This version does't work on symlinks to directories as python returns `True` on `os.path.isdir(symlink_to_directory)` – pevik Oct 01 '15 at 07:15
-
-
1This doesn't work for directories where the permissions disallow it, but you are root. At a shell prompt, you will get prompted "override rw------ for File.txt?" unless you use the -f flag. That works silently at the prompt while up above in python fails. – Matt Sep 13 '18 at 21:13
-
`os.remove` removes devices just fine; I just tried it. I don't understand the remarks about the code not working on device files and such. The POSIX syscall `unlink` doesn't distinguish between files and devices. – Kaz Oct 06 '19 at 00:03
-
this somehow does not work when the folder is a git repository, error message `PermissionError: [WinError 5] Access is denied: 'C:\\Codes\\team_lib\\temp_FR_537562\\.git\\objects\\pack\\pack-****.idx` – XYZ Aug 19 '22 at 07:02
-
1@XYZ not 100% sure this is the issue you're running into, but Windows often will not let you remove files if they're currently open by another process, and (at least in wsl) that is reported as a permission error that appears to be very similar to the error you'd receive if you didn't have write access to the file. is it possible that something is issuing/monitoring that directory? (I've often found VScode to be a culprit) – Gabriel Grant Sep 11 '22 at 00:25
-
@GabrielGrant, I agree. Most likely some git related files are opened in the cache in the VScode? I am not sure myself. But if I close all the programs and run in cmd, it solves the problem. – XYZ Sep 12 '22 at 01:15
import os
import shutil
def rm_r(path):
if not os.path.exists(path):
return
if os.path.isfile(path) or os.path.islink(path):
os.unlink(path)
else:
shutil.rmtree(path)
Slightly improved Gabriel Grant's version. This works also on symlinks to directories.
Note: function does not handle Un*x character and block devices (it would require to use stat module).

- 4,523
- 3
- 33
- 44
-
1You can probably handle devices by putting the `unlink` into the fallback case; do `rmtree` if you detect a directory. I.e. we don't have to specifically test for device node types. – Kaz Oct 05 '19 at 23:57
I know shutil.rmtree() is the recommended approach, but for me, it is just not reliable. I was running into instances where API would fail and the directory was not deleted.
The most robust approach I've found is:
import subprocess
import os
def remove_dir(d):
if os.name == 'nt':
subprocess.check_output(['cmd', '/C', 'rmdir', '/S', '/Q', os.path.abspath(d)])
else:
subprocess.check_output(['rm', '-rf', os.path.abspath(d)])

- 3,750
- 33
- 26
def delite(filepath):
import os, stat, sys
def intertwin(_list):
list1 = []
for i in _list:
list1 += i
return list1
allpath = os.walk(filepath)
walk = []
dirs = []
path = []
allfiles = []
for i in allpath:
walk.append(i)
for i in walk:
dirs.append(i[0])
for _dir in dirs:
os.chdir(_dir)
files = os.listdir(_dir)
files1 = []
for i in files:
files1.append(_dir + '\\' + i)
files = files1[:]
allfiles.append(files)
allfiles = intertwin(allfiles)
for i in allfiles:
os.chmod(i, stat.S_IRWXU)
allfiles.reverse()
os.chdir(sys.path[0])
for i in allfiles:
try:
os.remove(i)
except:
try:
os.rmdir(i)
except:
pass
os.chmod(filepath, stat.S_IRWXU)
try:
os.remove(filepath)
except:
os.rmdir(filepath)
allfiles.reverse()
os.chdir(sys.path[0])
for i in allfiles:
try:
os.remove(i)
except:
try:
os.rmdir(i)
except:
pass
os.chmod(filepath, stat.S_IRWXU)
try:
os.remove(filepath)
except:
os.rmdir(filepath)

- 1,518
- 1
- 14
- 23

- 35
- 3
-
Удаляет папку с файлами или файл, даже если стоит атрибут "Только чтение" Deletes a folder with files or a file, even if the attribute "Read only" – Pogramist May 28 '17 at 10:11
-
1In English, please: _Deletes a folder with files or a file, even if attributed "Read only"_ – JosefZ May 28 '17 at 10:11
-
1
A workaround for Windows where it blocks deletion of file is to truncate the file:
outputFile = open(r"filename.txt","w")
outputFile.truncate()
outputFile.close()
outputFile = open(r"filename.txt","a+")

- 361
- 4
- 20
shutil.rmtree() is right answer, but just look at another useful function - os.walk()

- 5,454
- 7
- 28
- 30
Just do this:
import os
dirname = "path_to_directory_to_remove"
os.system("rm -rf %s" % dirname)

- 63
- 3
-
2
-
2
-
1
-
2dangerous and platform dependent, but works, in the case where "-f" is required. None of the solutions above, except this one actually work for the "-f" required case. – Matt Sep 13 '18 at 20:37