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 目录本身。
备注:内容仅供参考。
