PAYATHON 2026

Python 如何递归删除目录并按模式保留指定内容?

数据阿明

结论

shutil.rmtree() 不支持 ignore 参数。若要递归删除目录中的内容并保留匹配项,可以用 os.scandir() 遍历目录,再用 fnmatch.fnmatchcase() 检查每一项的名称。匹配的文件或目录会被跳过,其余内容则递归删除。下面的实现会保留根目录本身。

import fnmatch
import os


def remove_contents(directory, patterns):
    with os.scandir(directory) as entries:
        for entry in entries:
            if any(fnmatch.fnmatchcase(entry.name, pattern) for pattern in patterns):
                continue

            if entry.is_dir(follow_symlinks=False):
                remove_contents(entry.path, patterns)
                os.rmdir(entry.path)
            else:
                os.unlink(entry.path)

调用示例:

remove_contents(source, ['donotdeletethis.txt'])

这会保留 source 及其子目录中名称匹配 donotdeletethis.txt 的项目,并删除其他文件和目录。模式会与每一级目录中的名称匹配,和 shutil.ignore_patterns() 一样,不会匹配完整路径。

处理规则

  • 匹配的目录会被整体跳过,目录中的内容也会保留。
  • entry.is_dir(follow_symlinks=False) 不会跟随目录符号链接。符号链接会通过 os.unlink() 删除,其目标不会被递归删除。
  • fnmatch.fnmatchcase() 区分大小写。若要忽略大小写,可以改用 fnmatch.fnmatch()。
  • 删除时若遇到权限不足等错误,异常会向上传递。调用前请确认目标路径正确,并确保进程有相应权限。

rmtree(source, destination, ...) 不是 shutil.rmtree() 的有效调用形式。shutil.rmtree() 删除指定目录树,不接收 destination 参数。上面的函数只清空 source 中的内容,不会删除 source 目录本身。

备注:内容仅供参考。