跳转到内容

快捷指令与脚本互相调用 ​

快捷指令擅长的是接入系统和应用的现成能力:读取剪贴板、处理照片、发通知、跨设备同步。Shell 脚本擅长的是文本处理、批量文件操作和调用命令行工具。

把两边接起来,你就不必在一侧硬撑。这一篇讲双向调用的方法,以及怎么划分职责。

开始之前 ​

需要先会建立基本的快捷指令,见第十篇:自动化。需要能在终端执行命令。

在快捷指令里运行脚本 ​

在快捷指令编辑器中搜索「运行 Shell 脚本」操作,拖进流程。几个要点:

输入怎么进来。 该操作可以接收上一步的输出。在「输入」下拉里选择作为标准输入传入,脚本里用 cat 读取;或者选择作为参数传入,脚本里用 $1 读取。两种方式行为不同,搞混会得到空值。

输出怎么出去。 脚本打印到标准输出的内容成为这一步的结果,可以接给下一个操作。所以调试时不要在脚本里乱 echo,多余的输出会一起传下去。

路径仍然是老问题。 和 launchd 一样,快捷指令运行脚本时的 PATH 与你终端里的不同。Homebrew 安装的命令要写绝对路径,例如 /opt/homebrew/bin/rg(Apple 芯片)或 /usr/local/bin/rg(Intel)。用 which 命令名 查出准确路径再填。

一个能立刻验证的例子——把输入的文本转成小写:

sh
cat | tr '[:upper:]' '[:lower:]'

cat 读取标准输入,tr 做字符替换,两个参数分别是要替换的字符集和替换成的字符集。

从终端触发快捷指令 ​

反方向用系统自带的 shortcuts 命令。

列出全部快捷指令:

sh
shortcuts list

运行其中一个:

sh
shortcuts run "快捷指令的名称"

名称含空格或中文时要加引号。传入内容:

sh
echo "要处理的文本" | shortcuts run "我的快捷指令"

管道符 | 把左边命令的输出送给右边作为输入。需要把结果拿回来时加 --output-path:

sh
shortcuts run "我的快捷指令" --output-path /tmp/result.txt

--output-path 指定把快捷指令的输出写到哪个文件。用 - 作为路径值表示写到标准输出。

职责怎么分 ​

不要把所有逻辑都堆在一侧。经验规则:

交给快捷指令交给脚本
读写照片、通讯录、日历、提醒事项文本解析与格式转换
发系统通知、弹出选择菜单批量重命名、按规则整理文件
接入分享菜单、触发式自动化调用命令行工具(ffmpeg、rg、Git)
在 iPhone、iPad 上也要能用需要循环、条件和错误处理的逻辑

最后一行值得展开:快捷指令能在 iPhone 上运行,Shell 脚本不能。需要跨设备的流程,逻辑尽量留在快捷指令一侧;只在 Mac 上跑的流程,复杂逻辑放脚本里可读性好得多。

快捷指令的循环和条件判断在流程稍长之后会变得很难读——一屏放不下、无法用版本库比较差异。超过十来步就该考虑把核心逻辑挪进脚本,快捷指令只负责取输入、给输出。

让它自己跑起来 ​

两条路径:

  • 快捷指令自身的自动化:在快捷指令 App 的「自动化」里按时间、连接充电器、连上某个 Wi-Fi 等条件触发。适合与设备状态相关的任务。
  • 交给 launchd:写一个 LaunchAgent 执行 shortcuts run,见用 launchd 让任务按时间和事件运行。适合需要精确调度、需要日志和退出码的任务。

选后者时注意,快捷指令若涉及照片、文稿等受保护数据,后台首次运行会因为没有人点「允许」而失败。先在终端手工跑一次完成授权。

检查结果 ​

sh
shortcuts list | head

能列出你的快捷指令,说明命令行工具正常。

然后建一个只有一步「运行 Shell 脚本」的快捷指令,脚本内容填 date,命名为「测试时间」,再从终端执行:

sh
shortcuts run "测试时间" --output-path -

应当输出当前时间。--output-path - 把结果打到终端。这条链路通了,说明双向调用都可用。

动手练习 ​

做一个两侧协作的小流程:

  1. 新建快捷指令「转小写」,只含一步「运行 Shell 脚本」,内容为 cat | tr '[:upper:]' '[:lower:]',输入设为标准输入。
  2. 在快捷指令 App 里点运行,用剪贴板内容测试。
  3. 从终端执行 echo "HELLO World" | shortcuts run "转小写" --output-path -。
  4. 故意把脚本里的 tr 改成 /nonexistent/tr,再跑一次,观察失败表现。
  5. 改回来确认恢复。

成功标准是第 3 步和第 2 步得到相同结果——同一个快捷指令,两种触发方式行为一致。第 4 步的意义是先见识一次失败的样子:快捷指令的报错信息通常比终端简略得多,这是把复杂逻辑放脚本里的另一个理由。

返回自动化与脚本