'Remove empty folders (Python)

This is the folder tree:

FOLDER\\
       \\1\\file
       \\2\\file
       \\3\\
       \\4\\file

The script should scan (loop) for each folder in FOLDER and check if the sub-folders are empty or not. If they are, they must be deleted.

My code, until now, is this:

folders = ([x[0] for x in os.walk(os.path.expanduser('~\\Desktop\\FOLDER\\DIGITS\\'))])
folders2= (folders[1:])

This scan for folders and, using folders2 begin from the firs folder in DIGITS. In DIGITS there are numbered directories: 1,2,3,4,etc

Now what? Tried using os.rmdir but it gives me an error, something about string. In fact, folders2 is a list, not a string, just saying...



Solution 1:[1]

Not sure what kind of error you get, this works perfectly for me:

import os

root = 'FOLDER'
folders = list(os.walk(root))[1:]

for folder in folders:
    # folder example: ('FOLDER/3', [], ['file'])
    if not folder[2]:
        os.rmdir(folder[0])

Solution 2:[2]

You can remove all empty folders and subfolder with the following snippet.

import os


def remove_empty_folders(path_abs):
    walk = list(os.walk(path_abs))
    for path, _, _ in walk[::-1]:
        if len(os.listdir(path)) == 0:
            os.remove(path)

if __name__ == '__main__':
    remove_empty_folders("your-path")

Solution 3:[3]

Delete folder only if it is empty:

import os
import shutil

if len(os.listdir(folder_path)) == 0: # Check if the folder is empty
    shutil.rmtree(folder_path) # If so, delete it

Solution 4:[4]

A few things to expand on other answers:

If you use os.walk(topdown=False), it goes in reverse order, so you encounter the child directories before the parents. Then if you track which directories you've deleted, you can delete parent directories recursively.

import os


def delete_empty_folders(root):

    deleted = set()
    
    for current_dir, subdirs, files in os.walk(root, topdown=False):

        still_has_subdirs = any(
            _ for subdir in subdirs
            if os.path.join(current_dir, subdir) not in deleted
        )
    
        if not any(files) and not still_has_subdirs:
            os.rmdir(current_dir)
            deleted.add(current_dir)

    return deleted

Solution 5:[5]

import os

directory = r'path-to-directory'

for entry in os.scandir(directory):
    if os.path.isdir(entry.path) and not os.listdir(entry.path) :
        os.rmdir(entry.path)

Here you can find a good introduction/explanation to scandir

Solution 6:[6]

Almost what Iván B. said but with a minor change that worked for me

import os, shutil
path_abs=('YourPath')
walk = list(os.walk(path_abs))
for path, _, _ in walk[::-1]:
    if len(os.listdir(path)) == 0:
        os.rmdir(path)

Solution 7:[7]

#LOOP THROUGH ALL SUBFOLDERS FIRST

import os
root = os.getcwd() #CHANGE THIS TO PATH IF REQUIRED
folders = sorted(list(os.walk(root))[1:],reverse=True)
for folder in folders:
    try:
        os.rmdir(folder[0])
    except OSError as error: 
        print("Directory '{}' can not be removed".format(folder[0])) 

This should go through all the sub-folders first and remove if empty folders. Not deleting non empty folders that a parent folders.

I know it an old post but I am old myself !!!

Solution 8:[8]

For empty folders deletion you can use this snippet.

import os


def drop_empty_folders(directory):
    """Verify that every empty folder removed in local storage."""

    for dirpath, dirnames, filenames in os.walk(directory, topdown=False):
        if not dirnames and not filenames:
            os.rmdir(dirpath)

Solution 9:[9]

If you are on UNIX system, you can use the "find" command in a python script with subprocess.
You search for directories with : -type d
You select empty directories with : -empty
You delete these directories with : -delete
You launch the command with subprocess.run

import subprocess

command = "find {} -type d -empty -delete".format(folder_path)  
subprocess.run(command, shell=True)

It is just 3 lines code.

Following @tripleee's advice, the code can be written like this :

import subprocess
path = "your path here"
command = ["find", path, "-type", "d", "-empty", "-delete"]
subprocess.run(command)

Solution 10:[10]

This answer fixes issues in the current accepted answer. The major issue there is that the condition to remove a directory has to be not filenames and not dirnames.

import os

def remove_empty_directories(root):
    for dirpath, dirnames, filenames in os.walk(root):
        if not filenames and not dirnames:
            os.rmdir(dirpath)

Solution 11:[11]

I suggest that you call this function, It is designed with an optional argument. If you set in_place to False it will not remove the folders it will just return them as a list. Meanwhile, if you set it to True the function will remove the empty folders regardless of the subdirectories tree depth.

P.S. In case you need a depth limitation you can analyze it by elements after root path.

import os
import shutil

def purge_dir(dir, in_place=False):

    deleted = []
    dir_tree = list(os.walk(dir, topdown=False))

    for tree_element in dir_tree:
        sub_dir = tree_element[0]
        is_empty = not len(os.listdir(sub_dir))
        if is_empty:
            deleted.append(sub_dir)

    if in_place:
        list(map(os.rmdir, deleted))

    return deleted

I suggest that you keep in_place set to False return back the empty folders and use it as you like since it is safer especially for security critical applications.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Iván B.
Solution 3
Solution 4 rcgale
Solution 5
Solution 6 Nuno André
Solution 7 user1184628
Solution 8
Solution 9 Community
Solution 10 sidcha
Solution 11 haddagart