简体   繁体   中英

How to find recursively empty directories in Python?

Similarly to GNU find 's find . -type d -empty -delete find . -type d -empty -delete I'd like to find empty directories including those with empty subdirectories (and subdirectories containing emtpy subdirs etc.), but without deleting them . Is there any existing solution or do I have to manually use os.walk (probably with topdown=False and keeping track of the empty subdirectories found so far)?

Here is a simple solution using a generator and os.walk :

import os

def find_empty_dirs(root_dir='.'):
    for dirpath, dirs, files in os.walk(root_dir):
        if not dirs and not files:
            yield dirpath

print list(find_empty_dirs())

I don't see why topdown=False is necessary, I don't think it changes anything.

This does consider directories that only contain empty directories to be non-empty themselves, but then so does find . -type d -empty find . -type d -empty .

Although, with some more testing, I see find . -type d -empty -delete find . -type d -empty -delete does delete the empty subdirectories first, and then the higher directories if that made them empty. But using os.walk for that won't work, as it reads the list of subdirectories before descending, even with topdown=False .

A recursive solution that deletes empty subdirectory trees could be:

import os

def recursive_delete_if_empty(path):
    """Recursively delete empty directories; return True
    if everything was deleted."""

    if not os.path.isdir(path):
        # If you also want to delete some files like desktop.ini, check
        # for that here, and return True if you delete them.
        return False

    # Note that the list comprehension here is necessary, a
    # generator expression would shortcut and we don't want that!
    if all([recursive_delete_if_empty(os.path.join(path, filename))
            for filename in os.listdir(path)]):
        # Either there was nothing here or it was all deleted
        os.rmdir(path)
        return True
    else:
        return False

Ok, here's my manual solution using os.walk . The function is_empty can of course be modified, eg to exclude hidden files, or in my example desktop.ini :

import os


def empty_dirs(root_dir='.', recursive=True):
    empty_dirs = []
    for root, dirs, files in os.walk(root_dir, topdown=False):
        #print root, dirs, files
        if recursive:
            all_subs_empty = True  # until proven otherwise
            for sub in dirs:
                full_sub = os.path.join(root, sub)
                if full_sub not in empty_dirs:
                    #print full_sub, "not empty"
                    all_subs_empty = False
                    break
        else:
            all_subs_empty = (len(dirs) == 0)
        if all_subs_empty and is_empty(files):
            empty_dirs.append(root)
            yield root


def is_empty(files):
    return (len(files) == 0 or files == ['desktop.ini'])


def find_empty_dirs(root_dir='.', recursive=True):
    return list(empty_dirs(root_dir, recursive))


print find_empty_dirs(recursive=False)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM