【问题标题】:How to find recursively empty directories in Python?如何在 Python 中递归查找空目录?
【发布时间】:2014-11-06 08:32:01
【问题描述】:

与 GNU findfind . -type d -empty -delete 类似,我想找到空目录,包括具有空子目录的目录(以及包含 emtpy 子目录等的子目录),但不删除它们。是否有任何现有的解决方案或者我必须手动使用os.walk(可能使用topdown=False 并跟踪到目前为止找到的空子目录)?

【问题讨论】:

  • 如果我确定在 Unix/Linux 上运行,我会尝试使用 os.walkPopen + find
  • @SergeBallesta 到目前为止,前者也是我最好的猜测。我想知道它是否没有库函数......或者可能是find 模块。这可能会简化很多事情。
  • @SergeBallesta I implemented it using os.walk,希望它足够 Pythonic...
  • @Close-vote 我不是在寻找库推荐,只是为了实现find 所做的Pythonic 方式(以可移植方式)。当然,“图书馆 XY 将其实现为 Z”仍然是一个有效的答案
  • 我添加了手动递归解决方案。

标签: python directory-structure subdirectory


【解决方案1】:

这是一个使用生成器和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())

我不明白为什么topdown=False 是必要的,我认为它不会改变任何东西。

这确实将仅包含空目录的目录视为非空目录,但find . -type d -empty 也是如此。

尽管经过更多测试,我看到find . -type d -empty -delete确实先删除空的子目录,然后再删除更高的目录(如果这使它们为空)。但是使用 os.walk 是行不通的,因为它会在下降之前读取子目​​录列表,即使使用 topdown=False

删除空子目录树的递归解决方案可能是:

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

【讨论】:

  • 很好奇 - 啊,我在问题中看到了我的错误,find . -type d -empty 也只能以我在使用 -delete 时的意思递归工作。恐怕我必须解决我的问题,尽管您的意见很受赞赏,但无论哪种方式,生成器听起来都更好
  • 我修改了my own answer 以包含一个生成器,但到目前为止我必须存储到目前为止找到的所有空子目录,这就是我需要topdown=False 的原因。但也许有 一种更简单的方法
【解决方案2】:

好的,这是我使用 os.walk 的手动解决方案。 is_empty 函数当然可以修改,例如排除隐藏文件,或者在我的示例中为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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    相关资源
    最近更新 更多