Python中快速比对两个目录并删除无对应同名文件的高效方法
高效删除无对应标注的图片:利用集合实现O(n)级比对
嘿,处理20万级别的文件比对,逐一遍历列表确实效率太低了——咱们直接用集合(Set)的快速查找特性就能解决,这能把时间复杂度从O(n²)降到O(n),速度提升不止一个量级!
核心思路
- 先把所有保留下来的
annotations目录下的XML文件名(去掉.xml后缀)存入一个集合——集合的成员检查是O(1)时间复杂度,比列表的O(n)快太多。 - 遍历
images目录下的所有图片文件,提取文件名(去掉.jpg后缀),检查这个文件名是否不在XML集合里;如果不在,就删除对应的图片。
代码实现(两种风格可选)
方式一:用Python标准库os模块
import os # 定义目录路径,根据你的实际路径修改 images_dir = "./images" annotations_dir = "./annotations" # 获取所有XML文件的无后缀文件名,存入集合 xml_filenames = set() for filename in os.listdir(annotations_dir): if filename.endswith(".xml"): # 去掉后缀,只保留文件名主体 name_without_ext = os.path.splitext(filename)[0] xml_filenames.add(name_without_ext) # 遍历图片目录,删除无对应XML的图片 count_deleted = 0 for filename in os.listdir(images_dir): if filename.endswith(".jpg"): name_without_ext = os.path.splitext(filename)[0] if name_without_ext not in xml_filenames: # 拼接完整路径并删除文件 img_path = os.path.join(images_dir, filename) os.remove(img_path) count_deleted += 1 print(f"共删除 {count_deleted} 张无对应标注的图片")
方式二:用更简洁的pathlib(Python 3.4+推荐)
from pathlib import Path # 定义目录路径 images_dir = Path("./images") annotations_dir = Path("./annotations") # 获取所有XML文件的无后缀文件名集合 xml_filenames = set(file.stem for file in annotations_dir.glob("*.xml")) # 遍历图片并删除无对应XML的文件 count_deleted = 0 for img_file in images_dir.glob("*.jpg"): if img_file.stem not in xml_filenames: img_file.unlink() count_deleted += 1 print(f"共删除 {count_deleted} 张无对应标注的图片")
为什么这种方法更快?
- 列表的
in操作是线性扫描,每检查一个元素都要遍历整个列表,20万张图片的话就是20万×20万=40亿次操作,慢到离谱。 - 集合的
in操作是哈希查找,平均只需要1次操作,20万张图片就是20万次操作,瞬间就能完成。
额外建议
- 先测试再删除:可以先把
os.remove()或unlink()换成print(img_path),确认要删除的文件确实是无对应XML的,避免误删。 - 处理异常:如果担心文件权限或文件不存在的问题,可以加
try-except块捕获异常:try: img_file.unlink() except OSError as e: print(f"删除文件 {img_file} 失败: {e}") - 内存占用:20万个字符串的集合占用内存非常小(大概几MB),完全不用担心内存问题。
内容的提问来源于stack exchange,提问作者Austin
相关产品推荐
相关产品推荐

