本文选自《Keyboard Maestro 进阶指引(增订版)》,限时试读中,欢迎选购完整栏目。

Keyboard Maestro 固然有十八般武艺,却难敌实践中的万千难题,而上一篇介绍的 AppleScript 只是方便操控部分软件,并非通用魔法。所幸还有一类脚本——Shell Script,可以调用大量系统自带的命令行工具1,若确有需要,还可以安装第三方工具,如下操作均无难度:截屏扫描二维码、解压 RAR 文件、自动开关 Wi-Fi……这相当于为 Keyboard Maestro 打开了一间配置豪华的军火库。
本文无意介绍一大堆基于 Shell Script 的 Macro,在我看来,那也是借花献佛,套壳而已。我更乐意说明如何使用 Shell Script,而最理想的效果,是您可以将任何好用的 Shell Script Based 动作移植到 Keyboard Maestro 中)——例如我发布过而无暇移植的几百个动作。
哪些任务适合交给 Shell Script
macOS 的 Shell Script 是个技术大熔炉,既继承了一部分 Unix 命令2,也有不少 macOS 专用命令,同时也可以调用第三方命令行工具。虽然近乎全能,但如果 Keyboard Maestro 已有相关模块,则一般没有必要从头写脚本,因此本篇的首要任务也是工作分配。粗略来看,适合交给 Shell Script 的任务也分三类:
第一类是和系统底层相关的 Unix 命令,例如给文件解锁。2023 年开始的微信强制给所有文件上锁,不重新授权就不能编辑,严重影响了用微信工作的人——估计是大部分人,包括我;而解决之道,似乎只有用命令行重新授权,有人就写了一段 Shell 脚本解决此番人祸。如果你想要一个和文件、文本或系统相关的功能而 Keyboard Maestro 无能为力,可以试试搜索 shell+关键词
,大概率可以找到对应的 Shell Script。
第二类是 macOS 专用命令,典型如 default write
开头的一系列神秘指令。当你想往 Launchpad 里多塞几个软件图标、想优化 Dock 显示效果或者想干掉修改文件拓展名时的恼人提示,网友或 GPT 一般会给你一串神秘命令,保证药到病除。其实,这些命令用于修改 macOS 的系统设置,并且包括许多暂无图形化界面的设置项。你可以在这里找到一份汇编,不一定最齐全,但数量相当大,足够充当参考资料。
还有一类是第三方命令行工具。没有人知道世界上有多少命令行工具,但仅仅著名的包管理器 HomeBrew 上起码就有五六千个3,而 Keyboard Maestro 自带模块比它低了一个数量级。说第三方命令是军火库,并不夸张。
Execute Shell Script 模块

Keyboard Maestro 依靠 Execute Shell Script 模块运行 Shell 脚本,Shell 并无 AppleScript 的奇怪限制,基本上你能在别处跑的脚本,也能直接塞进 Keyboard Maestro,起码我做过几百个 Macro,完全没有遇到需要外挂脚本的情况。换句话说,图中运行外挂脚本的选项一般不需要考虑。
和 AppleScript 类似,Shell 脚本也可以当作一个黑箱,重点关注输入和输出。Execute Shell Script 比 AppleScript 模块更科学而完整,既可以选择输入的数据来源,也能和 AppleScript 一样选择将结果放诸何处。不过,考虑到 Shell 脚本本身就能调用图中输入菜单里的所有数据,事实上也不需要专门在图形化界面中设定参数了——这样的脚本,也完整且易于移植。
在接收输入方面,Keyboard Maestro 可以直接在 Execute Shell Script 模块中使用标准的 Shell 变量写法:$KMVAR_变量名
。在 Shell 中,$变量名
本身就表示变量,例如 $@
在 Automator 和 LaunchBar 中均用于接收用户输入,可以把选中的文件或文本传送给脚本;但 Keyboard Maestro 另有方法。在 Keyboard Maestro 中的变量,都自动设 Shell 可以调用的环境变量,可用 $KMVAR_变量名
呼出,例如在预处理 PDF 时,我先将检测到的文件路径写入 Keyboard Maestro 变量 t
中,再通过 $KMVAR_t
在 Execute Shell Script 模块里使用。

不过,也不是总要使用变量。一些较为轻快的 Macro,例如把选中的文本转换为 Markdown 有序列表,就可以直接从剪贴板中读取数据——毕竟,你选中选中文本了,直接复制一下然后处理剪贴板多方便,不必折腾变量。

在 Execute Shell Script 中使用剪贴板数据的套路如下:
pbpaste | 这里是单行的 Shell 脚本 | pbcopy
pbpaste
表示从剪贴板中获取数据,管道符号 |
用于在几段命令之间传递数据,把符号左边的输出交给右边,当作后者的输入4,pbcopy
则将处理结果返还到剪贴板。

一些常见问题
脚本毕竟是外来物,难免在 Keyboard Maestro 中出现排斥反应,尤其是一些在终端(Terminal)中运行畅通无阻的命令,原模原样拷贝粘贴到 Keyboard Maestro 里却不断报错或毫无反应。其实,终端预设了一系列参数,而 Keyboard Maestro 则是一个相对于原始的环境,苟照抄他人脚本,则很容易运行失败。本节收录了一些常见问题并附上建议,您也可以在《macOS 自动化杂症自查篇》中查看更多疑难杂症和相应处方。
无法运行第三方命令行工具
估计不少读者都是冲着第三方命令行工具去的,可你如果直接把官方提供脚本粘到 Keyboard Maestro 里,几乎可以打赌,一定会运行失败。这是因为,在终端等地方运行 Shell Script 时,软件默认已经指定了一个 Shell,如同箭已搭在弦上;而在 Keyboard Maestro 中,还得先指定用哪个 Shell 来运行脚本——任何 macOS 系统中都不止一个 Shell。比较通用的做法是在任何涉及第三方命令行工具的脚本开头都加上一句:
PATH=$PATH:/usr/local/bin/
无法正常输出中文
网上的 Shell Script 资源大部分都来自英文社区,即便是 GPT,也不可避免地带着英文偏见,放到中文环境中运行很容易出现乱码。这事儿倒也容易解决,在出问题的脚本开头加上以下代码,即可正常输出中文。
export LANG="en_US.UTF-8"
小结
Shell Script 不是一个简单的模块,而是一扇连接大后方的门,可以调用几乎任何你能想象的命令行工具。本作若能带来惊鸿一瞥,都已足令我额手称庆。
事实上,一本小册子所能谈及的 Shell 之妙,远不及九牛一毛;而本篇的任务,只到打扫干净通往 Shell 的大门为止,之后的道路,还是任凭读者自己选择。
- Python 也可以用命令行交互,但本文为避免铺展过多,所谓的 Shell Script 仅指 bash 脚本,并不包括 Ruby、Perl 和 Python,何况这些脚本逐渐被移除出 macOS,读者还得先学会怎么把它们装回来。不过,考虑到 Python 随着机器学习而日益受欢迎,或许未来本作增订时会增加相关章节。 ↩
- 一般版本都比较老,例如
sed
,请先阅读手册后再使用,或者去网上找 macOS 专用版本,直接复制过来的大概率用不了。 ↩ - 包管理器,可以简单理解成命令行版本的 App Store。 ↩
- 管道隐喻——注意不是语言学上的——在 macOS 中很常见,Automator 图标上的小机器人举着的就是水管,而非很多人误以为的大炮。不同模块各司其职,每一环节负责一件事并把它做好,上一环节的输出交给下一环节作为输入,这是 Unix 哲学的遗风。 ↩