如今,无论是商业文件,电子书籍,还是学术论文,大多以 PDF(Portable Document Format,便携式文档格式)文件格式存储和分发。由于 PDF 具有跨平台、跨设备、且不易修改的特点,能够保持文件呈现的一致性,因此在互联网上得到了广泛的应用。借助扫描技术,PDF 甚至让前数字时代的书籍或文章「重见天日」,为信息传播发挥了重要作用,因此,PDF 被称为 世界上最重要的文件格式。可以说,在 2023 年使用电子设备,就不可避免地要与 PDF 文件打交道。
尽管 PDF 的使用相当广泛,各类 PDF 软件也层出不穷,但是 PDF 的很多特点和功能仍然不为人知,日常学习工作中遇到 PDF 相关的问题还是会让不少同学犯难。举个例子,我的一位爱书朋友热衷于将喜爱的纸质书扫描成 PDF 电子书,前段时间他遇到一个棘手的问题:扫描得到的 PDF 文件中,每一页包含书籍的两页,他想将其分割成单独的两页,在付费的 Adobe Acrobat Pro 中折腾了半天,他也没有搞明白究竟应该该如何实现。能找到的其他方法也不是没有,但全都需要付费,且价格还不便宜,因此他没有尝试。最终,在我的推荐下,没有花费一分钱,他使用开源的 MuPDF 轻松实现了这个需求1。
可见,发明 PDF 格式的 Adobe 公司推出的 Acrobat 也并非万能的,在实现某些 PDF 功能时并非总是最优选项。除此之外,Adobe Acrobat 的许多高级功能都需要付费使用,并且界面不够美观,个人不是很喜欢。有鉴于此,本文接下来将分享一些我日常用到的 PDF 处理技巧,这些技巧都是我在日常学习工作中遇到的,可能相对比较小众,但每一种方法都提供了免费的实现方式,让你无需 Adobe Acrobat 或其他付费 PDF 软件,也能轻松应对工作中处理 PDF 的问题。
本文分享的技巧主要使用命令行工具来实现,下面的表格列出了这些工具的主要信息,包括名称、语言、支持平台、许可方式、主要功能等。
名称 | 语言 | 支持平台 | 版本 | 界面 | 许可方式 | 主要功能 | 安装方式 (macOS) | 备注 |
---|---|---|---|---|---|---|---|---|
pdftk-java | Java | Linux, macOS, Windows | 3.3.3 | 命令行 | GNU-2.0 | 导出 PDF 元数据,合并、拆分、修复 PDF 等 | brew install pdftk-java |
本文使用的为 Java 移植版,PDFtk Server 原版已有超过 10 年未更新,停留在 2.02 版本,部分功能与 pdftk-java 有所不同。 |
Skim | Objective-C | macOS | 1.6.21 | 图形化应用 | BSD | 阅读和批注 PDF,默认将 PDF 标注存储为 Skim notes | brew install --cask skim |
本文使用的是 Skim 附带的两个命令行工具 SkimNotes 2.9.3 和 SkimPDF 1.3.4。 |
MuPDF | C | Linux, macOS, Windows, Android, iOS | 1.23.0 | Library | AGPL-3.0 | 轻量级 PDF、XPS 和电子书查看器 | brew install mupdf |
MuPDF 包括软件库、命令行工具和适用于各种平台的阅读器,本文只用到了它的命令行工具 mutool 。 |
pdfjam | Shell | Linux, macOS, 通过 Cygwin 支持 Windows | 3.10 | 命令行 | GPL-2.0 | 主要涉及 PDF 页面的处理 | 安装 TeX Live 发行版或下载 release 后安装 | pdfjam 为 LaTeX 包 pdfpages 提供了在命令行中的使用接口,依赖于 LaTeX 引擎和包。 |
pypdf | Python | Linux, macOS, Windows | 3.16.2 | Library | BSD | 通过 Python 对 PDF 进行分割、合并、裁剪和转换、提取文本等 | pip install pypdf |
2022 年 12 月以前,pypdf 的名称为 PyPDF2 。 |
为了让不熟悉命令行的朋友也能上手使用,我也提供了 macOS 平台上的自动化实现方案,包括 Keyboard Maestro、Automator(自动操作)和 Shortcuts(快捷指令),你可以点击 这个链接 下载文中提到的所有 Keyboard Maestro macros、Automator workflows 和 Shortcuts。后两个软件都是 macOS 自带的,完全免费,只有 Keyboard Maestro 是付费软件。作为 Mac 用户,我非常喜欢 Keyboard Maestro,也推荐你使用它。如果你还没有购买 Keyboard Maestro,可以使用少数派读者专属优惠码 SSPAI
享受八折优惠,只需 28.8 美元即可入手 Keyboard Maestro 11。关于学习如何系统使用 Keyboard Maestro,欢迎阅读由我撰写的少数派栏目《生产力超频:Keyboard Maestro 拯救效率》。
调整 PDF 页码标签
一般情况下,我们所说的 PDF 页码指的是物理页码,即 PDF 中从第 1 页开始递增的页码,每个 PDF 文档都有物理页码,这种页码被称作 page numbers,大多数情况下,page numbers 都使用阿拉伯数字计数。除此之外,在 PDF 特别是较长的 PDF 书籍中,还有另一种被称作 page folios 的页码,它是指 PDF 页面中页眉或页脚处的序列标记,可能是英文字母、罗马数字或阿拉伯数字,在 Adobe Acrobat 中也叫作 page labels。我们常说的某本书的第几页指的是 page folios,而不是 page numbers。例如下图中的 PDF 一共有 256 页,当前位于 page numbers 的第 19 页,page folios 的第 10 页。
在上图所示的 PDF 中,page numbers 和 page folios 不一致。当我们在 PDF 阅读软件中页码跳转框中输入阿拉伯数字 10 之后,会跳转到 page numbers 的第 10 页,而不是 page folios 的第 10 页(即这本书的第 10 页)。造成这种情况的原因是 PDF 书籍中的封面、版权、前言、目录等部分的 page numbers 通常使用的是英文字母或罗马数字,正文部分才是阿拉伯数字。为了方便阅读,我们通常需要将 page folios 和 page numbers 设置为相同的值。
在 Adobe Acrobat 中,我们可以选中需要调整的页面缩略图,然后右键点击「Page Labels…」,在弹出的对话框中设置需要调整的页面范围,然后调整 page labels,可以选择使用阿拉伯数字、英文字母、罗马数字或自定义标记,以及为其添加前缀,最后点击「OK」即可,如下图所示。
尽管在 Adobe Acrobat 中调整 page labels 非常直观,但是这种方法需要付费,而且操作比较繁琐,需要多次点击,不够方便。下面介绍另一种调整 PDF 页码的方法——使用命令行工具 PDFtk。这种方法无需付费,并且非常符合 Unix 哲学「一切皆文件」的原则。需要注意的是,由于原版 PDFtk2 不支持调整 PDF 页码标签的功能,因此下文使用的都是 pdftk-java
。
使用下面的命令,就可以将名为 input.pdf
的元数据 导出 为一个纯文本文件 metadata.text
:
|
|
使用文本编辑器打开生成的 metadata.text
,可以看到 input.pdf
的各种元数据,其中就包括页码标签信息,如下所示:
|
|
容易发现,每个 PDF 页码标签的元数据由 4 或 5 行组成:
PageLabelBegin
:开始一个页码标签PageLabelNewIndex
:页码标签开始的索引,对应 PDF 的 page numbersPageLabelStart
:页码标签开始的页码PageLabelPrefix
:页码标签的前缀(可选)PageLabelNumStyle
:页码标签的类型,包括NoNumber
(无页码)、DecimalArabicNumerals
(阿拉伯数字)、UppercaseLetters
(大写英文字母)、LowercaseLetters
(小写英文字母)、UppercaseRomanNumerals
(大写罗马数字)和LowercaseRomanNumerals
(小写罗马数字)。
上面的示例对应的 PDF 页码标签元数据可以解读为:
- 第 1 页的 page label 为自定义文本
Cover
- 第 2 页的 page label 为带有前缀
Page
的大写英文字母Page A
- 第 3 页的 page label 为大写英文字母
A
,依次递增 - 第 6 页的 page label 为小写英文字母
a
,依次递增 - 第 9 页的 page label 为大写罗马数字
I
,依次递增 - 第 12 页的 page label 为小写罗马数字
i
,依次递增 - 第 17 页的 page label 为阿拉伯数字
17
,依次递增直至最后一页
需要注意的是,不是每一个 PDF 都具有这些全部类型,有些 PDF 的元数据可能没有任何关于页码标签的内容,这种情况下,PDF 阅读器会使用阿拉伯数字 1 开始标记。
为了修改 PDF 的页码标签,我们需要先将 PDF 的页码标签元数据导出为文本文件,然后修改其中的页码标签信息,最后将修改后的元数据导入 PDF 文件,生成一个新的 PDF 文件。比如我们将上述示例中倒数第 3 行的 17
修改为 20
,就可以将 PDF 的 page labels 修改为从阿拉伯数字 20 开始,而不是之前的 17,如下图所示。
经过上面的分析,修改 PDF 页码标签的步骤就很清晰了:
- 使用
pdftk
导出 PDF 的元数据为文本文件 - 根据 PDF 页面信息,使用文本编辑器打开元数据文件,修改页码标签信息
- 使用
pdftk
将修改后的元数据导入 PDF,生成页码标签修改后的 PDF
尽管上述步骤非常简单明了,但每次都需要修改文件名称,对于不熟悉命令行的朋友来说,可能还是有点难以上手。因此,我制作了一个 Keyboard Maestro macro 来实现这一功能,如下图所示。
这个 macro 首先获取访达(Finder)中选中文件及其所在路径,然后保存为 Keyboard Maestro 中的变量 selected_pdf
。之后是一个条件判断,用于判断选中的文件是否是 PDF,如果不是,则弹出通知「No PDF was selected.」,然后取消执行 macro。如果选中的文件是 PDF 的话,则弹出一个提示框,让用户输入页码标签的起始页,这里包括了 3 种类型,也就是 3 个变量:
FirstPage
:第一页,通常为Cover
,默认值设置为 1LowercaseRomanNumerals
:小写罗马数字页码标签的起始页DecimalArabicNumerals
:阿拉伯数字页码标签的起始页
如果上述 3 个值留空的话,则表示不包括该类页码标签。接下来,Keyboard Maestro 将用户输入的值作为变量传递给下面的 Shell 脚本:
|
|
这段代码主要分为 6 个部分:
- 使用
export
命令将pdftk
命令所在的路径添加到PATH
环境变量中,这样就可以直接使用pdftk
命令,而不需要输入完整的路径。/opt/homebrew/bin
和/usr/local/bin
分别是 Homebrew 在 Apple Silicon Mac 上和 Intel Mac 上的默认安装路径。 - 使用
cd
命令切换到选中 PDF 文件所在的路径。 - 使用
pdftk
命令导出 PDF 的元数据为文本文件metadata.text
。 - 使用
sed
命令删除metadata.text
中已有的页码标签信息,然后使用cat
命令将用户输入的页码标签信息追加到metadata.text
中 - 使用
pdftk
命令将修改后的元数据导入 PDF,生成页码标签修改后的 PDF。 - 使用
rm
命令删除metadata.text
。
激活这个 macro 之后,在访达中选中需要修改页码标签的 PDF 文件,然后按下快捷键 ⌃ + ⌥ + L
或点击菜单栏的 Keyboard Maestro Engine 图标,在弹出的窗口中输入不同类型的页码标签的起始页,就可以得到页码标签修改后的 PDF 文件,使用效果见下图。
在上图的示例中,默认将第 1 页的 page label 设置为 Cover
,小写罗马数字的起始页为 2,阿拉伯数字的起始页为 5,生成的 PDF 的页码标签如下图所示。
需要注意的是,上述 macro 只包括了自定义的 Cover、小写罗马数字和阿拉伯数字这 3 种类型的页码标签,如果你需要调整其他类型的页码标签,可以参考上面的示例,自行修改 Shell 脚本中的代码。需要注意的是,KMVAR_
是 Keyboard Maestro 中 Shell 脚本使用变量所必需的前缀,不可省略。