文档转 PDF(doc-to-pdf)
用 LibreOffice(soffice)无头模式把 Office 文档本地转成 PDF:不联网、不上传、源文件不改动。脚本已封装串行转换、失败重试与转换后校验,请直接调用脚本,不要自己另起 soffice 命令——soffice 同一实例并发会互相冲突,这正是脚本被封装出来的原因。
功能
| 能力 | 说明 |
|---|---|
| 支持格式 | docx / doc(Word)、xlsx / xls(Excel)、pptx / ppt(PowerPoint)、txt、rtf、odt / ods / odp、csv |
| 单文件 | -o 指定输出 PDF 路径(可改名),或 -d 指定输出目录;默认输出到源文件同目录、同名 .pdf |
| 批量 | 多个文件、shell 通配符(*.docx)、整个目录(--input);逐个串行转换,打印成功/失败清单 |
| 自动校验 | 每个输出检查:PDF 存在、非 0 字节、PyMuPDF 可打开且页数 > 0;失败自动重试 1 次 |
| 结果报告 | 打印每个文件"源大小 → PDF 大小 → 页数",最后汇总;退出码 0=全部成功,1=有失败 |
| 超时保护 | 单文件默认 120 秒,--timeout 可调大;超时自动终止 soffice 进程组 |
工作流程
- 确认输入:先确认源文件存在且扩展名受支持(用
ls或 glob)。不支持的格式(如.pages、.wps)直接告知用户并建议先另存为受支持格式,不要盲试。 - 选择模式:
- 单个文件:python3 <技能目录>/scripts/doc2pdf.py 报告.docx -o 报告.pdf
- 多个文件 / 目录:python3 <技能目录>/scripts/doc2pdf.py 文件1 文件2 -d 输出目录,或--input 目录 -d 输出目录 - 读取输出:脚本逐个打印"源大小 → PDF 大小 → 页数"与成功/失败标记,最后一行是汇总。
- 检查退出码:
0全部成功;1存在失败。失败时按汇总清单逐条向用户解释原因(格式不支持 / 文件损坏 / 超时),不要静默忽略,也不要把失败文件算进交付成果。 - 交付:向用户报告每个 PDF 的绝对路径、大小、页数;批量场景给出"成功 N / 失败 M"清单。
命令参考
# 单文件:指定输出 PDF 路径(文件名可与源不同)
python3 doc2pdf.py 报告.docx -o 报告.pdf
# 单文件:指定输出目录(输出为 目录/报告.pdf)
python3 doc2pdf.py 报告.docx -d ./pdf_out
# 批量:shell 通配符
python3 doc2pdf.py *.docx
# 批量:多个文件 + 输出目录
python3 doc2pdf.py a.docx b.xlsx c.pptx -d ./pdf_out
# 批量:整个目录(扫描全部支持格式)
python3 doc2pdf.py --input ./docs -d ./pdf_out
# 大文件调大超时(秒)
python3 doc2pdf.py 大文件.pptx --timeout 300
| 参数 | 说明 |
|---|---|
文件/目录(位置参数) |
待转换文件(支持通配符)或目录;目录会扫描全部支持格式 |
-o / --output 输出.pdf |
单文件模式的输出 PDF 路径(仅限恰好 1 个输入;必须以 .pdf 结尾) |
-d / --outdir 目录 |
输出目录(默认与源文件同目录) |
-i / --input 目录 |
批量模式:转换该目录下全部支持格式的文件 |
--timeout 秒 |
单文件转换超时,默认 120 秒 |
--help |
查看中文帮助 |
示例对话
示例 1:单文件转换
> 用户:把 ./季度总结.docx 转成 PDF
>
> 助手:确认文件存在后执行:
> bash
> python3 "${SKILL_DIR:-$PWD/.workbuddy/skills/doc-to-pdf}/scripts/doc2pdf.py" \
> ./季度总结.docx -o ./季度总结.pdf
>
> 输出显示"[成功] … 3 页"。回复用户:转换完成,PDF 共 3 页、约 48 KB,路径 ./季度总结.pdf。
示例 2:批量转换 + 失败清单
> 用户:把 ./docs 里的文档全部转成 PDF,放到 docs/pdf 子目录
>
> 助手:先 ls 确认目录内容(6 个文件,其中 1 个 .pages),然后执行:
> bash
> python3 "${SKILL_DIR:-$PWD/.workbuddy/skills/doc-to-pdf}/scripts/doc2pdf.py" \
> --input ./docs -d ./docs/pdf
>
> 脚本输出"成功 5/5,失败 0",并提示跳过 1 个不支持的 .pages 文件。回复用户:5 个文档已转好(逐个列出页数);xxx.pages 不支持转换,如需要请先另存为 docx/pptx。
运行环境
- 脚本:
scripts/doc2pdf.py(相对技能根目录) - Python:3.9+
- 第三方库:
PyMuPDF(pip install PyMuPDF) - 外部命令:
soffice
开工前先跑一次自检,缺什么当场补,别等跑到一半报错:
python3 -c "import fitz" 2>/dev/null || echo "缺 PyMuPDF,请执行 pip install PyMuPDF"
python3 -c "import pymupdf" 2>/dev/null || echo "缺 PyMuPDF,请执行 pip install PyMuPDF"
command -v soffice >/dev/null 2>&1 || echo "缺 soffice,请先安装再重试"
> 缺依赖时用中文告诉用户缺什么、装完就能用,不要把 Python 的英文 traceback 原样贴给用户。
注意事项
- 不做 PDF 转 Word:PDF → docx/xlsx 的反向转换格式还原质量差,本技能不做,请见谅。遇到这类请求请直接向用户说明,不要用本脚本硬转。
- 串行是硬约束:soffice 同一实例并发会冲突,脚本内部已强制串行(失败重试 1 次)并使用独立用户配置;不要并行运行多个本脚本或多个 soffice。
- 排版还原有限:源文档指定了系统没有的字体时,会以相近字体替代(Noto CJK 已装,中文正常);SmartArt、艺术字、复杂公式、Excel 复杂分页转换后可能有差异。请把"页数"报告给用户,页数为 0 或异常偏多都值得复查。
- 加密文档会失败:带打开密码的 Office 文档无法转换,脚本会明确报错。
- 覆盖同名输出:输出位置已有同名
.pdf会被新结果覆盖。 - xlsx / csv 特性:Excel 转 PDF 按打印区域分页、多个 sheet 一起输出;csv 由 Calc 打开后转出,仅简单表格效果。
- 调试产物放 /tmp:测试、造样本时不要污染用户工作区。