如何在Python3中递归删除空文件夹?

8 投票
3 回答
6216 浏览
提问于 2025-04-18 05:31

我想要删除一个文件夹里的空文件夹。

def remove_empty_dir(path):
    try:
        os.rmdir(path)
    except OSError:
        pass

def remove_empty_dirs(path):
    for root, dirnames, filenames in os.walk(path):
        for dirname in dirnames:
            remove_empty_dir(os.path.realpath(os.path.join(root, dirname)))

remove_empty_dirs(path)

我也试过:

import shutil
shutil.rmtree(path)

但是这样会把所有东西都删掉,包括那些有内容的文件夹。问题是我需要从里面到外面来删除,这样如果我有:

root_folder
  child_folder1
    grandchild_folder1.1 (empty)
  child_folder2
    granchild_folder2.1
    granchild_folder2.2 (empty)

程序应该删除 grandchild_folder1.1、child_folder1 和 child_folder2.2,但不删除其他的文件夹。

3 个回答

1
def remove_empty_dirs(dir_path):
    p1 = subprocess.Popen(["find", dir_path, "-type", "d", "-empty", "-print0"], stdout=subprocess.PIPE,)
    p2 = subprocess.Popen(["xargs", "-0", "-r", "rmdir"], stdin=p1.stdout, stdout=subprocess.PIPE)
    p1.stdout.close()
    p2.communicate()

当然可以!请把你想要翻译的内容发给我,我会帮你把它变得简单易懂。

5

在Python 3中,使用pathlib库可以用一行代码搞定这件事(除了引入库的部分)。下面的代码片段中,target_path是你想要清理的文件夹树的根目录的字符串:

from pathlib import Path
import os

[os.removedirs(p) for p in Path(target_path).glob('**/*') if p.is_dir() and len(list(p.iterdir())) == 0]

为了让内容更简单易懂,这里用没有列表推导的方式写了一遍同样的代码。

for p in Path(target_path).glob('**/*'):
    if p.is_dir() and len(list(p.iterdir())) == 0:
        os.removedirs(p)

这里有个有趣的地方,就是if语句用来筛选出文件系统树上那些空的文件夹。os.removedirs()这个函数会删除所有在一个空文件夹上面的空文件夹。如果在一条分支上有多个空文件夹,删除最后一个空文件夹会让os.removedirs()向上遍历这条分支。所以在一次循环中,所有的空文件夹都会被删除,不需要递归调用!

11

os.walk 是一个函数,它有一个可选的参数叫 topdown(默认值是 True)。

如果你把这个参数设置为 topdown=False,那么程序会先从子目录开始遍历。

def remove_empty_dirs(path):
    for root, dirnames, filenames in os.walk(path, topdown=False):
        for dirname in dirnames:
            remove_empty_dir(os.path.realpath(os.path.join(root, dirname)))

撰写回答