macOS 如何把任何文档"打印"成 PDF?RWTS-PDFwriter 免费虚拟打印机完整上手指南
【免费下载链接】RWTS-PDFwriterAn OSX print to pdf-file printer driver项目地址: https://gitcode.com/gh_mirrors/rw/RWTS-PDFwriter
在 macOS 上做文档转换时,你很可能遇到过这样的场景:网页排版精美却只能截图保存、合同模板想批量导出成 PDF、代码里的技术报告要定期归档成册——系统自带的"打印为 PDF"每次都要手动选保存位置、改文件名,批量处理时几乎没法用。RWTS-PDFwriter 正是为解决这类需求而生的开源虚拟打印机驱动:装上之后,系统里会多出一台名为 PDFwriter 的"打印机",任何应用里按下 ⌘P、选中它、点打印,文档就自动变成 PDF 文件落到你指定的文件夹里。本文从实际使用场景出发,带你完整走一遍从安装、配置、日常使用到自动化进阶的全过程,全程免费、无订阅、无广告。
从一个"存网页"的小需求说起
做研究或写文档的人大概都有过这种经历:看到一篇重要的网页文章,想完整保存下来。截图是最常见的做法,但截出来的图文字是"死"的——没法搜索、没法复制、放大就糊。而"另存为网页"又经常把布局打乱,图片和样式支离破碎。
其实 macOS 早就给了一个官方方案:打印对话框右下角的"PDF"按钮,选择"存储为 PDF"。这个功能本身没问题,但它每次都要你手动指定保存路径、手动输入文件名,而且没有记忆功能。当你一个月要归档几十份网页资料时,这种重复操作会让人抓狂。
更关键的是,这种系统级方案没法被脚本调用。你想写个自动化任务把某个目录里的文件全部转成 PDF?系统自带的方案做不到。
而虚拟打印机(Virtual Printer)的思路完全不同:它假装自己是一台真实打印机,接管所有应用的打印输出,然后把数据流直接写成文件。这样你就获得了一个系统级、任何应用通用、可脚本化的 PDF 生成入口。RWTS-PDFwriter 就是干这个的。
RWTS-PDFwriter 是什么:一台"不存在"的打印机
先看一个直观的定义:RWTS-PDFwriter 是一个运行在 macOS 11.0 及以上系统的开源打印驱动,功能上类似 Windows 上老牌免费的 CutePDF。它由两部分组成:
- 核心后端(
pdfwriter/main.swift):一个标准的 CUPS 打印后端程序。CUPS 是 macOS 底层的打印系统,几乎所有打印任务都要经过它。后端程序负责接收打印数据、校验格式、写出文件。 - 配套工具(
PDFWriter Utility/ContentView.swift):一个用 SwiftUI 写的图形小工具,用来创建 PDF 输出文件夹、管理卸载脚本。
值得强调的是,这个项目虽然只有几百行代码,却把"简单可靠"做到了极致。它不常驻后台、不占用内存、不弹广告,只在有打印任务的时候被 CUPS 临时唤醒,干完活就走。
项目的血脉也值得一提:RWTS-PDFwriter 脱胎于 Simone Karin Lehmann 的 Lisanet PDFWriter,而 Lisanet 又源于 Linux 上著名的 CUPS-PDF。换句话说,这是一条传承了近二十年的成熟技术路线,稳定性有相当保障。
背后的设计:为什么它又快又稳
真正让我对这个小项目刮目相看的,是它几个细节处的工程考量。你不需要懂代码也能理解这些设计——它们直接决定了你日常使用的体验。
每个用户一个专属目录
后端程序会把 PDF 输出到/var/spool/pdfwriter/下以用户名命名的子目录里,比如/var/spool/pdfwriter/zhangsan/。这意味着:
- 多人共用一台 Mac 时,各人的文件互不干扰;
- 每个目录的权限和文件权限都与系统账户严格绑定(私有文件 600,匿名用户 666);
- 文件的所有权归属于实际打印的那个人,而不是 root。
这种"命名空间隔离"的设计,让它在办公室共用电脑的场景下也能放心使用。
原子创建,杜绝同名覆盖
很多同类工具处理同名文件时的做法是"直接覆盖"或"随机改名",容易造成数据丢失。RWTS-PDFwriter 用的是操作系统层面的O_CREAT | O_EXCL原子操作:创建文件时如果发现重名,就自动在文件名后追加-1、-2……直到成功。注意是"追加编号"而不是"覆盖旧文件",这从机制上杜绝了并发打印时两个任务互相覆盖的竞态问题(race condition)。
严格的文件名校验
打印时 macOS 会传递文档标题作为文件名,但标题里可能带/这种非法字符。后端程序会先把斜杠替换成冒号,再截掉扩展名,最后拼上.pdf。同时文件名长度被限制在 200 字符以内,避免超出文件系统限制。如果一个文档没有标题(比如命令行直接管道输入),它会被命名为Untitled.pdf。
先验证,再落盘
后端程序在读入数据流时,会先检查文件头四个字节是否为%PDF。如果不是,直接报错取消任务,绝不会写出一堆乱码文件。这意味着从打印源头就能拦截格式错误。
五分钟完成安装:从源码到可用
官方提供两种方式:直接下载编译好的安装包,或者自己从源码构建。这里重点讲从源码构建的完整流程。
准备工作
你需要一台装有 Xcode 命令行工具的 macOS 设备。构建脚本会自动处理编译、打包、生成 PPD 驱动文件(打印机的"说明书",描述打印机支持哪些纸张尺寸、颜色等能力)等一系列步骤。
# 克隆项目源码 git clone https://gitcode.com/gh_mirrors/rw/RWTS-PDFwriter # 进入项目目录 cd RWTS-PDFwriter # 执行构建脚本(自动编译并生成安装包) ./build/buildscript.sh脚本跑完后,项目根目录下会出现RWTS-PDFwriter.pkg安装包。直接双击安装,输入管理员密码即可。安装过程中系统会自动注册打印机驱动,完成后打开"系统偏好设置 > 打印机与扫描仪",你就能看到 PDFwriter 这台虚拟打印机了。
如果你希望安装包经过 Apple 公证(notarization,苹果的安全校验机制),需要额外传一个钥匙串配置文件参数,前提是你有合法的开发者证书:
./build/buildscript.sh -n "<Your Keychain Profile>"首次配置:创建 PDF 输出文件夹
安装完成后,系统会自动打开 PDFWriter Utility 工具,界面非常简洁——一个打印机图标加两个按钮:
点击Create PDF Destination Folder,在弹出的对话框里选择一个你希望 PDF 落盘的文件夹(比如~/Documents/PDF_Output)。工具会在后台把这个位置与/var/spool/pdfwriter/你的用户名/建立符号链接,相当于把打印机的"出纸口"重定向到了你选的位置。
需要注意两点:一是创建完文件夹后要退出这个工具,安装流程才算真正完成;二是工具不支持"替换已有位置",如果你之前配置过其他目录,先不要重复操作。如果你跳过这步直接打印,文件会落到默认的/var/spool/pdfwriter/下,也完全能用。
第一次"打印":把它变成 PDF
配置完成后,它的使用方式简单到让人怀疑是不是漏了什么步骤:就用平时打印文档的方式,把打印机换成 PDFwriter 就行。
拿保存网页举例:
- 在 Safari 或 Chrome 中打开目标网页;
- 按下
⌘ + P调出打印对话框; - 打印机选择PDFwriter;
- 点击"打印"。
整个过程一气呵成,随后打开你之前配置的输出文件夹,一份与页面排版完全一致的 PDF 已经躺在那里了,文件名自动取网页标题。文字是可搜索、可复制的,这是截图永远比不上的。
Word、Excel、Keynote、PDF 阅读器、邮件客户端……任何能触发打印对话框的应用,理论上都能用这台"打印机"输出 PDF。这就是虚拟打印机最大的价值:你不需要学习任何新软件,只需要换个打印目标。
打印机装好了,去系统设置里确认一下
安装完成后,打开"系统偏好设置 > 打印机与扫描仪",你会看到 PDFwriter 出现在打印机列表里,状态为"空闲"(Idle):
在这里你可以把它设为默认打印机,或者查看打印队列。更有意思的是Options & Supplies...按钮,进入后切换到 Utility 标签页,会看到"Open Printer Utility"的入口:
这个入口很实用:电脑上有多个用户时,其他用户不需要重装软件,从这里就能打开 PDFWriter Utility,创建属于自己的 PDF 输出目录。也就是说,一台机器上每个人都可以有自己的"出纸口",彼此互不干扰。
进阶玩法:命令行与自动化
如果说图形界面的用法只是"方便",那命令行才是把这款工具的效率彻底释放出来的方式。
批量转换文本文件
配合lpr命令,你可以循环把一堆文本文件转成 PDF,文件名自动取自-T参数指定的标题:
# 把当前目录所有 .txt 文件批量转为 PDF for file in *.txt; do cat "$file" | lpr -P PDFwriter -T "$(basename "$file" .txt)" done注意-P PDFwriter指定打印机名,-T指定文档标题(会成为 PDF 文件名)。
监控文件夹,自动转换
结合fswatch(macOS 上的文件监控工具),你可以做一个"丢进去就自动转 PDF"的文件夹:
fswatch -0 ~/Documents/ToPrint | while read -d "" event; do if [[ "$event" == *.docx ]] || [[ "$event" == *.pages ]]; then open -a "Microsoft Word" "$event" && sleep 2 osascript -e 'tell application "Microsoft Word" to print active document' fi done把 PDFwriter 设为默认打印机后,这段脚本会监听指定文件夹,新放入的文档自动被打开、打印、转成 PDF。适合会议资料、发票、合同等需要统一归档的场景。
在开发流程里用起来
对开发者来说,把 PDFwriter 接进构建流水线能省下不少手工操作:
# 生成 API 文档 PDF doxygen Doxyfile && cd latex && make && lpr -P PDFwriter refman.pdf # 把代码统计报告直接转 PDF cloc ./src --by-file --csv | lpr -P PDFwriter # 架构图导出 plantuml -tpng architecture.puml && convert architecture.png architecture.pdf && lpr -P PDFwriter architecture.pdf这些都是即插即用的思路,关键在于lpr -P PDFwriter这个入口对任何能输出到标准输入的内容都成立。
遇到问题怎么办:一份排错清单
用这类系统级工具,偶尔会遇到些小状况。把最常见的几个问题和对应解法列在这里,遇到时直接照着做即可。
问题一:打印机没出现在列表里多半是驱动注册出了问题,先检查驱动文件是否就位,再重启打印服务:
# 检查驱动安装 ls -la /Library/Printers/RWTS/PDFwriter/ # 重新加载 CUPS 打印服务 sudo launchctl unload /System/Library/LaunchDaemons/org.cups.cupsd.plist sudo launchctl load /System/Library/LaunchDaemons/org.cups.cupsd.plist问题二:打印任务报错,没有 PDF 生成先看输出目录是否存在、权限是否正确:
ls -la /var/spool/pdfwriter/再查看 CUPS 的错误日志定位具体原因:
tail -f /var/log/cups/error_log日志里如果出现 "not compatible",说明应用输出的数据流不是标准 PDF,通常是驱动或应用本身的兼容问题。
问题三:文件太多,想清理打印队列
# 取消所有排队任务 cancel -a PDFwriter问题四:想临时禁用打印共享、减少系统开销
sudo cupsctl --no-remote-printers --no-remote-admin --no-share-printers完全卸载:一条脚本搞定
很多工具"安装容易卸载难",RWTS-PDFwriter 在这点上做得相当干净。打开 PDFWriter Utility,点击Reveal Uninstall script按钮,系统会打开/Library/Printers/RWTS/PDFwriter/目录,里面有一个uninstall脚本。运行它并输入管理员密码,驱动、打印机注册、后端配置会被全部移除,而你已生成的 PDF 文件会原样保留,不会有任何数据损失。
开发者视角:源码里有哪些值得看的细节
如果你对技术实现感兴趣,这个项目的源码非常值得一读——它短小精悍,几乎没有多余代码。
核心后端(pdfwriter/main.swift)只有一百多行,却完整演示了一个 CUPS 后端该有的全部要素:参数解析(job-id user title copies options [file])、setuid 权限提升检查、PDF 头校验、用户目录创建与权限设置、原子文件创建。尤其是那个O_CREAT | O_EXCL加EEXIST重试的循环,是处理并发写文件问题的教科书级写法。
配置工具(PDFWriter Utility/ContentView.swift)则展示了如何用 SwiftUI 在几十行内完成一个实用的系统工具:NSSavePanel 选择目录、符号链接创建、进程调用(用/usr/bin/open打开卸载目录),麻雀虽小五脏俱全。
驱动文件(build/PDFWriter.drv)里有一个关键配置Filter application/vnd.cups-pdf 0 -,这行声明了驱动接受 CUPS 的 PDF 数据流,是整个"打印成 PDF"机制的核心。同时它支持从 A0 到信封、照片纸的几乎所有标准纸张尺寸,默认纸张为 A4。
构建脚本(build/buildscript.sh)则是一份很好的 macOS 安装包制作参考:xcodebuild 编译 → pkgbuild 打包 → productbuild 生成安装器 → 可选签名与公证,全流程自动化。
最后的建议:谁适合用它
如果你属于以下任何一种情况,RWTS-PDFwriter 都值得一试:
- 普通办公用户:经常要把网页、文档存成 PDF 归档,受够了每次手动选路径;
- 多用户共用 Mac 的家庭或团队:需要每个人各自独立的 PDF 输出目录;
- 开发者与效率控:想把 PDF 生成接入脚本、自动化流程或 CI 工具链;
- 开源爱好者:想研究一个"小而美"的 CUPS 后端到底怎么写。
整个项目基于 GPL v2 许可证发布,代码完全开放,你可以自由修改、分发,甚至集成进自己的软件(前提是同样以 GPL 协议开源)。对于一个每天都要用、救过我好几次"存档危机"的小工具来说,这份透明和免费显得格外珍贵。
如果你也在 macOS 上被"存 PDF"这件事烦过,不妨花五分钟装上它,然后打开你最常用的那个应用,⌘P、选 PDFwriter、打印——从此告别逐份手动保存。
【免费下载链接】RWTS-PDFwriterAn OSX print to pdf-file printer driver项目地址: https://gitcode.com/gh_mirrors/rw/RWTS-PDFwriter
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考