我的知识记录

Python批量校验文件是否损坏教程

用Python批量检查图片、PDF、ZIP、Office文件是否损坏,尝试打开解析,损坏的文件标记出来,避免备份归档后才发现打不开。

Python批量校验文件是否损坏

场景痛点

从U盘、网盘拷了一堆文件到本地,当时没一个个打开检查,过了半年要用才发现好几个文件打不开——图片半拉、PDF报错、ZIP解压失败。手动一个个双击打开测试,几百个文件能点一下午。用Python按文件类型分别调用对应的解析库尝试打开,能正常读完就说明没坏,报错的就是损坏文件,一键出清单。

用到的库

pip install Pillow pdfplumber openpyxl python-docx

图片校验用 Pillow,PDF用 pdfplumber,Excel用 openpyxl,Word用 python-docx,ZIP用标准库。

完整代码

import zipfile
from pathlib import Path
from openpyxl import load_workbook
from docx import Document
from PIL import Image
import pdfplumber


def check_image(p: Path) -> tuple:
"""尝试用Pillow完整读取图片,校验是否损坏。"""
try:
with Image.open(p) as img:
img.load()  # 强制完整解码
return True, ""
except Exception as e:
return False, str(e)


def check_pdf(p: Path) -> tuple:
"""打开PDF并读取页数,校验是否损坏。"""
try:
with pdfplumber.open(p) as pdf:
_ = len(pdf.pages)
return True, ""
except Exception as e:
return False, str(e)


def check_xlsx(p: Path) -> tuple:
"""用openpyxl打开Excel,校验是否损坏。"""
try:
wb = load_workbook(p, read_only=True)
wb.close()
return True, ""
except Exception as e:
return False, str(e)


def check_docx(p: Path) -> tuple:
"""用python-docx打开Word,校验是否损坏。"""
try:
doc = Document(str(p))
_ = len(doc.paragraphs)
return True, ""
except Exception as e:
return False, str(e)


def check_zip(p: Path) -> tuple:
"""测试ZIP完整性。"""
try:
with zipfile.ZipFile(p) as zf:
bad = zf.testzip()  # 返回第一个损坏文件的名字,None表示全部正常
if bad is None:
return True, ""
return False, f"压缩包内 {bad} 损坏"
except Exception as e:
return False, str(e)


# 文件后缀 -> 校验函数
CHECKERS = {
".jpg": check_image, ".jpeg": check_image, ".png": check_image,
".bmp": check_image, ".gif": check_image,
".pdf": check_pdf,
".xlsx": check_xlsx, ".xlsm": check_xlsx,
".docx": check_docx,
".zip": check_zip,
}


def batch_check(folder: str):
"""扫描目录,校验所有支持的文件。"""
root = Path(folder)
results = []
for p in root.rglob("*"):
if not p.is_file():
continue
ext = p.suffix.lower()
checker = CHECKERS.get(ext)
if checker is None:
continue
ok, err = checker(p)
status = "正常" if ok else "损坏"
results.append({"path": str(p), "status": status, "error": err})
print(f"[{status}] {p.name}" + (f"  -> {err}" if err else ""))
return results


def export_to_excel(results: list, out_path: str):
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.title = "文件校验报告"
ws.append(["序号", "文件路径", "状态", "错误信息"])
for idx, r in enumerate(results, 1):
ws.append([idx, r["path"], r["status"], r["error"]])
ws.column_dimensions['A'].width = 8
ws.column_dimensions['B'].width = 80
ws.column_dimensions['C'].width = 10
ws.column_dimensions['D'].width = 50
wb.save(out_path)


if __name__ == "__main__":
FOLDER = r"D:\工作资料\备份"
results = batch_check(FOLDER)
bad = sum(1 for r in results if r["status"] == "损坏")
print(f"\n共校验 {len(results)} 个文件,损坏 {bad} 个")
export_to_excel(results, r"D:\工作资料\校验报告.xlsx")

代码讲解

按文件类型分派校验函数:图片用 Pillowimg.load() 强制完整解码,只打开不解码不算真正校验;PDF用 pdfplumber 打开并读取页数;Excel用 openpyxl 以只读模式打开;Word用 python-docx 读段落数;ZIP用 testzip() 逐个校验CRC。每种校验函数都返回 (是否正常, 错误信息) 二元组,统一格式方便汇总。CHECKERS 字典把后缀映射到校验函数,新增类型只需加一个函数和一行映射。rglob("*") 递归扫描所有子目录。

运行结果

控制台逐文件打印 [正常][损坏],损坏的附带错误原因。最后生成 校验报告.xlsx,四列:序号、文件路径、状态、错误信息。打开Excel按状态筛选,只看损坏的文件,从备份里重新拷贝覆盖即可。

注意事项

  • 每个库只能校验它认识的格式,.xls(老格式)openpyxl读不了,需要xlrd;.doc(老Word)python-docx读不了,需要win32com。
  • 大PDF校验会慢,因为要完整解析。几千个PDF建议分批跑。
  • 校验图片时 img.load() 必须调用,只 Image.open 不会真正解码像素,发现不了损坏。
  • 加密的Office文件会报错(无法打开),不算损坏,错误信息里能看出来。

Python批量校验文件是否损坏教程

标签:

更新时间:2026-09-14 21:24:42

上一篇:Python批量压缩文件为zip教程:一行命令搞定多文件打包

下一篇:Python批量同步两个文件夹教程