Python批量复制含关键词文件教程
用Python递归搜索文件名含指定关键词的文件,按原目录结构批量复制到目标文件夹,重名自动加序号,适合整理素材、归档项目文件。
场景痛点
项目做完了,要把所有带"XX项目"字样的图纸、合同、方案整理出来归档,结果这些文件散落在十几个子目录里,手动一个一个找、一个一个复制,半天还漏了好几个。用Python先按关键词搜出来,再按原来的目录结构复制到新文件夹,一分钟搞定,重名文件还自动加序号不覆盖。
用到的库
pip install openpyxl
核心用标准库 os、pathlib、shutil,日志清单导出用 openpyxl。
完整代码
import os
import shutil
from pathlib import Path
from openpyxl import Workbook
def copy_files_by_keyword(src_root: str, dst_root: str,
keywords: list,
keep_structure: bool = True):
"""
在 src_root 下找文件名含任意关键词的文件,复制到 dst_root。
keep_structure: True 则保留原目录层级,False 则全部平铺到目标根目录。
"""
src = Path(src_root)
dst = Path(dst_root)
dst.mkdir(parents=True, exist_ok=True)
copied = []
skipped = []
for dirpath, _, filenames in os.walk(src):
for name in filenames:
# 关键词匹配(不区分大小写)
lower_name = name.lower()
if not any(kw.lower() in lower_name for kw in keywords):
continue
src_file = Path(dirpath) / name
# 决定目标路径
if keep_structure:
rel = src_file.relative_to(src)
dst_file = dst / rel
dst_file.parent.mkdir(parents=True, exist_ok=True)
else:
dst_file = dst / name
# 重名自动加序号
dst_file = _deduplicate(dst_file)
try:
shutil.copy2(src_file, dst_file)
copied.append(str(dst_file))
except (OSError, shutil.SameFileError) as e:
skipped.append((str(src_file), str(e)))
return copied, skipped
def _deduplicate(path: Path) -> Path:
"""如果目标已存在,自动加 _1、_2 后缀,避免覆盖。"""
if not path.exists():
return path
stem = path.stem
suffix = path.suffix
parent = path.parent
i = 1
while True:
candidate = parent / f"{stem}_{i}{suffix}"
if not candidate.exists():
return candidate
i += 1
def export_log(copied: list, skipped: list, out_path: str):
wb = Workbook()
ws = wb.active
ws.title = "复制日志"
ws.append(["状态", "文件路径", "备注"])
for p in copied:
ws.append(["成功", p, ""])
for p, err in skipped:
ws.append(["失败", p, err])
ws.column_dimensions['A'].width = 8
ws.column_dimensions['B'].width = 90
ws.column_dimensions['C'].width = 40
wb.save(out_path)
if __name__ == "__main__":
SRC = r"D:\工作资料"
DST = r"D:\归档\XX项目汇总"
KEYWORDS = ["XX项目", "2025方案"]
copied, skipped = copy_files_by_keyword(SRC, DST, KEYWORDS,
keep_structure=True)
print(f"成功复制 {len(copied)} 个文件")
print(f"跳过/失败 {len(skipped)} 个")
export_log(copied, skipped, r"D:\归档\复制日志.xlsx")
print("日志已导出:D:\\归档\\复制日志.xlsx")
代码讲解
shutil.copy2 比 copy 好,它会把原文件的修改时间、访问时间一起复制过去,归档时时间戳不丢。keep_structure=True 时用 relative_to 算出文件在源目录里的相对路径,再拼到目标目录上,这样 src/a/b/c.pdf 会复制到 dst/a/b/c.pdf,层级关系保留。_deduplicate 函数处理重名:如果目标路径已经存在,就在文件名后加 _1、_2,循环到不重为止,绝对不会覆盖已有文件。日志分成功和失败两组,失败原因一并记录,方便排查权限问题。
运行结果
目标文件夹 XX项目汇总 下按原目录结构生成所有命中文件。控制台打印成功/失败数量,同时在 D:\归档\ 下生成 复制日志.xlsx,三列:状态、文件路径、备注。
注意事项
shutil.copy2复制的是副本,原文件不动,安全。要剪切的话换成shutil.move。- 跨盘复制大文件会比较慢,量大时先小范围测试。
- 目标目录如果在源目录内部,会递归扫到刚复制的文件,建议目标目录放在源目录外面。
- 文件名带特殊字符(冒号、问号)在Windows下会失败,脚本会记到失败列表里。

更新时间:2026-09-14 21:22:28
上一篇:Python创建多层文件夹目录:mkdirs一行建完整路径