一、结论先给
PDF 合并拆分的难不在"能不能做",而在做完之后书签、页码、表单、字体对不对。选型看这张表:
| 场景 | 方案 | 说明 |
|---|---|---|
| 临时几份、不涉密 | 浏览器在线合并 | 文件不出本机,最快 |
| 几十上百份、要自动化 | qpdf / pdftk 命令行 |
可写进脚本定时跑 |
| 要按书签/章节拆 | pdftk burst 或 Python pikepdf |
在线工具通常只能按页拆 |
| 加密/有权限的 PDF | 先解密再合并 | 知道口令才能合并 |
| 合并后体积暴涨 | 合并完再压缩 | 字体重复嵌入是主因 |
👉 不想装任何软件,直接用 PDF 合并(在线) 和 PDF 拆分(在线),全程在浏览器里跑,文件不上传服务器。
二、在线合并:顺序、书签与预览
2.1 顺序是合并第一坑
合并工具按你添加的顺序拼装,拖进去之后一定要确认缩略图顺序。常见翻车:
- 一次性选中 30 个文件,系统按文件名排序而不是你想要的章节顺序(
第10章排在第2章前面,因为字符串比较1<2); - 补了一份"附录"进去,结果排在正文中间。
规避办法:文件名用零填充(01-、02-…),或者合并工具支持拖拽排序时逐个调整后再点合并。
2.2 合并后常见的四件事
| 现象 | 原因 | 处理 |
|---|---|---|
| 书签(目录)只剩第一份的 | 多数工具不合并 outline | 用 pdftk 或 pikepdf 保留书签 |
| 页眉页码错乱 | 原文件自带页码 | 合并后重新加页码,或统一页脚 |
| 体积比原始之和还大 | 多次重复嵌入同一套中文字体(一套 3-10MB) | 合并后过一遍压缩 |
| 页面大小不一(A4 混 A3) | 源文件规格不同 | 先统一页面尺寸再合并 |
2.3 加密文件能不能合并
能,但必须先输入正确口令解密。带"禁止打印/禁止复制"权限的 PDF,只要你知道口令(或有权限的 PDF 无口令也能打开),就可以合并。合并产物默认不继承原文件的密码——这是一件需要注意的事:把机密文件的页面合并进普通文件后,那份机密内容就变成明文了。
三、在线拆分:三种维度
| 拆分维度 | 适用 | 举例 |
|---|---|---|
| 按页码范围 | 最常用 | 1-5、1,3,7、1-3,8-10 |
| 固定页数切分 | 批量上传系统有限制时 | 每 10 页一个文件 |
| 按文件大小切分 | 邮件附件 20MB 限制 | 每个不超过 10MB |
页码范围的写法各家略有差异,通用的是逗号分隔 + 连字符区间,- 表示区间,end 或 $ 表示最后一页。
👉 拆完如果要转成图片发给别人,用 PDF 转图片(在线);反过来把一堆图片合成 PDF 用 图片转 PDF。
四、命令行方案一:pdftk(最老牌,语法直观)
# 安装
yum install -y pdftk # 部分发行版需先装 EPEL,或用 pdftk-java
apt install -y pdftk-java
# 合并(按顺序)
pdftk 01.pdf 02.pdf 03.pdf cat output all.pdf
# 合并一个目录下所有 pdf(按文件名排序)
pdftk $(ls *.pdf | sort) cat output all.pdf
# 保留书签(关键参数)
pdftk A=01.pdf B=02.pdf cat A B output all.pdf
# 拆分:每页一个文件,输出 pg_0001.pdf ...
pdftk all.pdf burst output pg_%04d.pdf
# 拆分:取指定页
pdftk all.pdf cat 1-5 output part1.pdf
pdftk all.pdf cat 1 3 7 output pick.pdf
pdftk all.pdf cat 1-endodd output odd.pdf # 奇数页
pdftk all.pdf cat 1-endeven output even.pdf # 偶数页
# 带口令的文件
pdftk secret.pdf input_pw 123456 cat output plain.pdf
# 旋转(扫描件横躺时)
pdftk in.pdf cat 1-endright output rotated.pdf # 全部顺时针 90°
burst 会同时生成 doc_data.txt,里面记着书签和页码信息,需要按章节拆时很有用。
五、命令行方案二:qpdf(更快,适合大批量)
yum install -y qpdf # apt install -y qpdf
# 合并
qpdf --empty --pages 01.pdf 02.pdf 03.pdf -- all.pdf
# 按页范围合并(每个文件只取部分页,语法:文件 起始-结束)
qpdf --empty --pages a.pdf 1-5 b.pdf 1-3 -- out.pdf
# 拆分
qpdf all.pdf --pages . 1-10 -- part1.pdf
qpdf all.pdf --pages . 11-20 -- part2.pdf
# 解密
qpdf --decrypt --password=123456 in.pdf out.pdf
# 查看页数
qpdf --show-npages all.pdf
qpdf 对大文件(几百 MB)的处理速度明显好于 pdftk,且内存占用低,做批量脚本首选它。
六、命令行方案三:Python pikepdf(要按书签拆就用它)
pip3 install pikepdf
import pikepdf, os
# 按书签拆分:每个一级书签一个文件
def split_by_outline(src, outdir='out'):
os.makedirs(outdir, exist_ok=True)
pdf = pikepdf.open(src)
marks = [(o.destination[0].objgen if False else None) for o in []]
outlines = list(pdf.open_outline())
if not outlines:
print('该文件没有书签,改用按页拆分')
return
# 取每个一级书签的起始页
starts = []
for item in outlines:
if item.level == 1:
starts.append((item.title, item.destination[0]))
starts.append(('__END__', len(pdf.pages)))
for i in range(len(starts) - 1):
title, s = starts[i]
_, e = starts[i + 1]
dst = pikepdf.Pdf.new()
dst.pages.extend(pdf.pages[s:e])
safe = ''.join(c for c in title if c not in '/\\:*?"<>|')[:50]
dst.save(f'{outdir}/{i+1:02d}_{safe}.pdf')
print(f'{safe}: 第 {s+1}-{e} 页')
split_by_outline('book.pdf')
简单的按页拆:
import pikepdf
def split_fixed(src, size=10, outdir='out'):
import os; os.makedirs(outdir, exist_ok=True)
pdf = pikepdf.open(src)
n = len(pdf.pages)
for start in range(0, n, size):
dst = pikepdf.Pdf.new()
dst.pages.extend(pdf.pages[start:start + size])
dst.save(f'{outdir}/part_{start//size + 1:03d}.pdf')
print(f'共 {n} 页,切成 {(n + size - 1)//size} 份')
split_fixed('all.pdf', size=10)
七、批量实战:按目录合并并压缩
一个常见需求:几十个合同扫描件,按客户目录合并成一份。
#!/usr/bin/env bash
set -euo pipefail
# 用法:./merge.sh 客户目录
dir="${1:?用法: $0 <目录>}"
out="${dir}/_merged.pdf"
mapfile -t files < <(find "$dir" -maxdepth 1 -name '*.pdf' | sort)
[ ${#files[@]} -eq 0 ] && { echo "目录里没有 pdf"; exit 1; }
qpdf --empty --pages "${files[@]}" -- "$out"
echo "合并完成:$out($(qpdf --show-npages "$out") 页,$(du -h "$out" | cut -f1))"
合并完体积大就再压一道,可以用在线 PDF 压缩 过一遍,通常能砍掉一半以上。
7.1 产物校验(交付前必做)
# 结构完整性检查,有损坏会报 warning / error
qpdf --check merged.pdf | tail -5
# 基本信息(需装 poppler-utils)
pdfinfo merged.pdf | grep -E "^(Pages|Page size|Encrypted|File size)"
pdftotext merged.pdf - | head -20 # 抽一段文字确认内容没串
# 页数对账:合并结果应等于各源文件页数之和
qpdf --show-npages 01.pdf 02.pdf 03.pdf merged.pdf
7.2 命令行压缩(不想用在线工具时)
# ghostscript:效果最好,画质分档
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 \
-dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH \
-sOutputFile=merged_small.pdf merged.pdf
# 档位:/screen(72dpi 最小) /ebook(150dpi 推荐) /printer(300dpi) /prepress(最高)
# 扫描件专用(黑白 + 降采样,体积能砍到 1/5)
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook \
-dColorImageResolution=150 -dGrayImageResolution=150 -dMonoImageResolution=300 \
-dNOPAUSE -dQUIET -dBATCH -sOutputFile=scan_small.pdf scan.pdf
压缩后一定要抽几页对比清晰度,合同、发票这类要打印的材料压过头会糊到看不清。
八、常见误区
- 文件名没零填充:
第10章排在第2章前,合并顺序全乱。用01、02开头。 - 合并完就发:没检查页码和书签,客户收到的文档目录点不动。
- 加密文件合并后以为还保密:密码不会继承,明文就明文了。
- 用 Word 另存 PDF 再合并:Word 转出的 PDF 常把整套字体嵌进去,几份合并就几十 MB。
- 扫描件合并后不 OCR:能看不能搜,客户想复制文字时抓瞎。
rm掉原文件:合并失败就全没了,产物校验完再清理。
九、几条纪律
- 合并前先按目标顺序整理好文件名,别指望工具猜。
- 涉密文档优先用离线/在线纯前端方案,别传到不明网站。
- 大批量用 qpdf,按书签拆用 pikepdf,临时手动用在线工具。
- 合并后必查三件事:顺序、书签、体积。
- 产物验证(页数、能否打开)之前,原文件一律保留。
- 重复的机械操作写成脚本,把"合并→压缩→重命名→归档"串成一条命令。