331

I'm having a problem with deleting empty directories. Here is my code:

for dirpath, dirnames, filenames in os.walk(dir_to_search):
    # other codes

    try:
        os.rmdir(dirpath)
    except OSError as ex:
        print(ex)

The argument dir_to_search is where I'm passing the directory where the work needs to be done. That directory looks like this:

test/20/...
test/22/...
test/25/...
test/26/...

Note that all the above folders are empty. When I run this script the folders 20,25 alone gets deleted! But the folders 25 and 26 aren't deleted, even though they are empty folders.

Edit:

The exception that I'm getting are:

[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/26'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/25'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27/tmp'

Where am I making a mistake?

Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
sriram
  • 8,562
  • 19
  • 63
  • 82
  • 1
    are you sure they don't have hidden files? – Jeff Oct 29 '12 at 08:22
  • Is an exception or traceback printed? If so - it would help if you added that to the question – Ngure Nyaga Oct 29 '12 at 08:23
  • @Jeff: Yes I'm sure. In fact in my ubuntu machine I tried `rmdir /path/to/25th/folder` is deleting the entire directory. Which means that directory is an empty one! – sriram Oct 29 '12 at 08:29
  • 2
    Possible 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) of both question AND answer – Trevor Boyd Smith Oct 17 '16 at 21:27

12 Answers12

682

Try shutil.rmtree:

import shutil
shutil.rmtree('/path/to/your/dir/')
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Tomek
  • 6,944
  • 1
  • 13
  • 3
  • 8
    Does the `rmtree` deleted the entire directory? I guess it is similar to the one `rm -Rf $DIR` – sriram Oct 29 '12 at 08:31
  • 16
    Be careful as rmtree deletes the files too. As asked, the question was how to delete EMPTY directories.The docs for os.walk give an example that almost exactly matches this question: `import os for root, dirs, files in os.walk(top, topdown=False): for name in dirs: os.rmdir(os.path.join(root, name)) ` – DaveSawyer Nov 30 '18 at 18:32
  • is there something wrong witht his solution? why are there more answers needed ? :/ – Charlie Parker Nov 13 '22 at 20:39
  • @CharlieParker - there's nothing wrong with this answer. The reason for other answers is sometimes people maybe don't know the idiomatic way of doing something or they have a specific reason/use case not to use the idiomatic way, or, they want to highlight a different approach for whatever reason. If you want to dig in then you should open a new question. – keithpjolley Apr 17 '23 at 17:51
44

Here's my pure pathlib recursive directory unlinker:

from pathlib import Path

def rmdir(directory):
    directory = Path(directory)
    for item in directory.iterdir():
        if item.is_dir():
            rmdir(item)
        else:
            item.unlink()
    directory.rmdir()

rmdir(Path("dir/"))
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
mitch
  • 1,870
  • 15
  • 12
37

The default behavior of os.walk() is to walk from root to leaf. Set topdown=False in os.walk() to walk from leaf to root.

Leland Hepworth
  • 876
  • 9
  • 16
lqs
  • 1,434
  • 11
  • 20
16

Try rmtree() in shutil from the Python standard library

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
microo8
  • 3,568
  • 5
  • 37
  • 67
  • 1
    Does the `rmtree` deleted the entire directory? I guess it is similar to the one `rm -Rf $DIR` – sriram Oct 29 '12 at 08:32
  • 2
    from docs: "Delete an entire directory tree; path must point to a directory (but not a symbolic link to a directory). If ignore_errors is true, errors resulting from failed removals will be ignored; if false or omitted, such errors are handled by calling a handler specified by onerror or, if that is omitted, they raise an exception." – microo8 Oct 29 '12 at 08:36
7

better to use absolute path and import only the rmtree function from shutil import rmtree as this is a large package the above line will only import the required function.

from shutil import rmtree
rmtree('directory-absolute-path')
Gajender
  • 107
  • 1
  • 6
6

Just for the next guy searching for a micropython solution, this works purely based on os (listdir, remove, rmdir). It is neither complete (especially in errorhandling) nor fancy, it will however work in most circumstances.

def deltree(target):
    print("deltree", target)
    for d in os.listdir(target):
        try:
            deltree(target + '/' + d)
        except OSError:
            os.remove(target + '/' + d)

    os.rmdir(target)
Justus Wingert
  • 472
  • 4
  • 9
4

The command (given by Tomek) can't delete a file, if it is read only. therefore, one can use -

import os, sys
import stat

def del_evenReadonly(action, name, exc):
    os.chmod(name, stat.S_IWRITE)
    os.remove(name)

if  os.path.exists("test/qt_env"):
    shutil.rmtree('test/qt_env',onerror=del_evenReadonly)
Azat Ibrakov
  • 9,998
  • 9
  • 38
  • 50
Monir
  • 1,402
  • 14
  • 16
  • 2
    when trying your code with my own folder to be deleted, I get an error saying: `NameError: name 'stat' is not defined`. How has it been defined? – nnako Jul 30 '18 at 15:22
  • 1
    The stat module defines constants and functions for interpreting the results of os.stat(), os.fstat() and os.lstat(). what you can try : import os, sys from stat import * – Monir Aug 06 '18 at 12:59
2

The command os.removedirs is the tool for the job, if you are only looking for a single path to delete, e.g.:

os.removedirs("a/b/c/empty1/empty2/empty3")

will remove empty1/empty2/empty3, but leave a/b/c (presuming that c has some other contents).

    removedirs(name)
        removedirs(name)
        
        Super-rmdir; remove a leaf directory and all empty intermediate
        ones.  Works like rmdir except that, if the leaf directory is
        successfully removed, directories corresponding to rightmost path
        segments will be pruned away until either the whole path is
        consumed or an error occurs.  Errors during this latter phase are
        ignored -- they generally mean that a directory was not empty.
Cireo
  • 4,197
  • 1
  • 19
  • 24
1

Here is a recursive solution:

def clear_folder(dir):
    if os.path.exists(dir):
        for the_file in os.listdir(dir):
            file_path = os.path.join(dir, the_file)
            try:
                if os.path.isfile(file_path):
                    os.unlink(file_path)
                else:
                    clear_folder(file_path)
                    os.rmdir(file_path)
            except Exception as e:
                print(e)
Tobias Ernst
  • 4,214
  • 1
  • 32
  • 30
1

Here's another pure-pathlib solution, but without recursion:

from pathlib import Path
from typing import Union

def del_empty_dirs(base: Union[Path, str]):
    base = Path(base)
    for p in sorted(base.glob('**/*'), reverse=True):
        if p.is_dir():
            p.chmod(0o666)
            p.rmdir()
        else:
            raise RuntimeError(f'{p.parent} is not empty!')
    base.rmdir()
pepoluan
  • 6,132
  • 4
  • 46
  • 76
1

Here is a pythonic and recursion-less solution

>>> for e in sorted(p.rglob('**/*'), key=lambda v: v.is_dir()):
...     try:
...         e.unlink()
...     except IsADirectoryError:
...         e.rmdir()

The rglob() gives you all files and directories recursively in the path p. The sorted() with its key argument takes care that the result is ordered by files first and directories at the end. This makes it possible to make all directories empty with deleting their files first.

The try...except... part prevents you from using cheap if statements.

buhtz
  • 10,774
  • 18
  • 76
  • 149
-3

For Linux users, you can simply run the shell command in a pythonic way

import os
os.system("rm -r /home/user/folder1  /home/user/folder2  ...")

If facing any issue then instead of rm -r use rm -rf but remember f will delete the directory forcefully.

Where rm stands for remove, -r for recursively and -rf for recursively + forcefully.

Note: It doesn't matter either the directories are empty or not, they'll get deleted.

Garvit
  • 312
  • 3
  • 12