【059】10周 如何实现自动化解压和挂载 | 实用技巧

OscarGong
2017年11月01日

如何实现自动化解压和挂载 | 实用技巧

| 本文为付费栏目文章,您已订阅,可阅读全文 |
Mac 用户一定会经常重复的一个操作是:把来源各异的 dmg 文件挂载1 、zip 文件解压,把其中的 .app 文件拖到 ~/Applications/ 文件夹下,dmg 文件挂载后还要再进行一下弹出的动作,经历的次数多了就会思考如何简化这个操作。

用 LaunchBar 来实现自动化操作

最初我是使用 Automator 的 Folder Action 功能来完成这个需求的,但是并不是所有的 dmg、zip 内都是可以直接复制到~/Applications/ 的 .app 文件(比如从 Parallels Desktop 网站上下载下来的 DMG 内就是需要双击后才运行的 Install Parallels Desktop.app),所以 Automator Folder Action 的局限也很明显:它无法做区分,会闷头闷脑的对所有符合筛选条件的文件都做操作,易产生错误。这时候就有了更高更细致的需求。
LaunchBar 就很适合快速筛选,控制传入参数并给出及时的动态反馈。
最后完成的效果:激活 LaunchBar → 运行「Install Apps」动作,这时动作会列出~/Downloads下的 dmg、zip、app、pkg 文件,用方向键选择需要处理的文件后回车。
如果选择的是 dmg 文件:会自动进行挂载 → 然后自动提取 dmg 中的 app 文件 → 如果该 app 正在运行,会自动退出 → 自动复制到 ~/Applications/下 → 弹出 dmg 文件并删除 → 重新打开该 app

dmg
如果选择是 zip 文件:zip 文件会解压后,提取其中的 app 文件,并复制到~/Applications/下,同样的也会询问是否删除:

zip
如果选择的是 pkg 文件:则会直接运行:

pkg
如果是 dmg 文件中又包含了 zip 文件的情况,会递归查找,直至找到 .app 文件。

如果你对该动作的制作流程感兴趣,还可以接着往下看。

如何制作

打开 LaunchBar,输入AE 打开 LaunchBar Action Editor,点左下角加号新建一个 New Action,命名为「Install Apps」。
本质上所有的 LaunchBar Action 其实都是 .lbaction 文件,是 Package 类型,其结构与大部分 macOS 的 bundle 文件都是类似的,填在 General 部分关于 Action 的元信息会被保存在 Info.plist 下。当 Action 还在开发的过程中时,建议勾选「Enable Debug Log」,通过 /Applications/Utilities/Console.app 查看运行情况。
关于 Info.plist 中所有的 metadata 信息的文档可以查阅这里
随后来到 Scripts 部分。

关于「Scripts」


Scripts
在一个 LaunchBar Action 内可以提供不同的几种 Scripts 用于不同的用途,具体而言:
  • Default Script:每个动作都需要有的脚本,是在大部分情况下运行的脚本,同时也是在按下 时、使用「Send To」动作激活动作时和把光标移到这个动作上然后按时会运行的脚本。
  • Suggestions Script:提示脚本或者叫建议脚本,在文本输入期间会运行的脚本,根据已经输入的字符,猜测用户可能的输入意向。当用户输入了完整的搜索词,或选中了一个建议,按下 ,对应的字符串会作为输入传递到 Default Script。
  • Action URL Script:LaunchBar 支持 URL Scheme,当在其他程序中通过自定义的 URL Scheme 激活 LaunchBar Action 时,会运行 Action URL Script。
几个属性:
  • Run in background:动作是否需要在后台运行。如果不选中此项,LaunchBar 会保持在前台运行,直至运行结束或返回了用户结果。
  • Live feedback enabled:动态反馈。选中此项,脚本会动态的对用户输入做出反馈。与 Suggestions Script 类似,但对结果的处理方式不同。
  • Keep window active:保持窗口活跃。LaunchBar 窗口在脚本运行过程中会保持运行在前台如果选中此项。
  • Reapply last string argument with ⇧ ↩:选中后,在 Action 中按下 ⇧ ↩ 会再次输入上次的输入内容。
  • Requires argument:如不勾选,Action 会直接执行。勾选后,Action 可以接受参数。
  • Accepts string argument 与 Accepts path argument:规定了 Action 能接受哪种类型的输入。
  • Return result:LaunchBar Action 能够解析 Action 输出的 JSON、XML、PLIST 格式的复杂结果,但是如果 Action 只需要返回简单的结果,在此处做选择,可以强制 LaunchBar 把结果作为字符串或路径来处理。
对于「Install Apps」这个动作,我使用了 Default Script 和 Suggestions Script,皆使用 Shell Script 完成,可能需要您有一些基础的 Shell 编程基础

具体实现

功能上,Suggestions Script 负责从 ~/Downloads/中筛选出需要的 zip、app、dmg、pkg 类型文件。Default Script 把从 Suggestions Script 传递来的文件做进一步处理:解压、复制、挂载或打开,并询问用户相关细节。

Suggestions Script

代码较长,这里不全部放出,完整代码在此
前半部分基础工作不谈,只提一下与 LaunchBar 交互的部分:
echo '<?xml version="1.0"?><items>'
while IFS= read -r line
do
FILE=$(basename "$line")
KBSIZE=$(du -ks "$line" | awk '{print $1}')
SIZE=$(echo "scale=2;x=($KBSIZE/1024); if (x<1) print 0; x" | bc)
ADDED=$(stat "$line" | awk '{print $22, $21, $24}' | sed 's|\"||g')
SETICON=$(icon "$line")
echo '<item>
<arg>'$line'</arg>
<title>'$HOME'/Downloads/'$FILE'</title>
<subtitle>Size: '$SIZE' MB | Date Added: '$ADDED' | '$line'</subtitle>
<icon type="fileicon">'$SETICON'</icon>
</item>'
done <<< "$TABELA"
echo '</items>'

Action
为了使 LaunchBar 能够解析脚本反馈回的(复杂)数据,需将数据按照相关标签的规定以 XML 形式返回。

Default Script

Default Script 中,使用isrunning()函数来判断 app 是否正在运行,如果正在运行则询问用户是否退出。使用checkzip()checkdmg() 分别对 zip 和 dmg 文件做处理。
因为 Shell Script 无法使用图形界面与用户进行互动,相关的位置使用了 Apple Script 来实现系统通知,弹出对话框等操作,像:
delete(){
osascript <<EOF

set the_path to "$QUERY"
set the_folder to (POSIX file the_path) as alias

set answer to the button returned of (display dialog "The process of copying / installing app has ended.\n\nWould you like to remove source file now?" buttons {"Yes", "No"} default button 2 with icon caution with title "Install App")

if (answer = "Yes") then
tell application "Finder"
move the_folder to trash
end tell
end if
EOF
}

  1. 过去的日子里,软件的发行主要靠光盘。DMG 文件是 macOS 下的「磁盘映像」文件,作为软件分发格式,它有着:能控制 Finder 窗口背景,可以添加许可证,添加文字描述,可以加密等好处。因为延续了光盘的传统,所以 DMG 文件在使用时,有着「挂载」(把光盘插入光驱)和「弹出」(从光驱中取出光盘)的操作。

上一期
关于工作中的短暂休息 | 效率思维
下一期
用 Photoshop 制作 GIF 动画 | 工作日志
 
精选评论(2) 我的评论
  • MagisDing
    在Default Script的选择上,AppleScript、Javascript、Shell Sript各有什么优势和局限性吗?
    2017年11月02日
    • 少数派编辑部
      Apple Script 是可以运行 Shell Script 的,像:do shell script "ls /Applications/"

      同时 Shell Script 也是可以运行 Apple Script 的,像: osascript -e 'set x to "a"' -e 'say x'

      所以其实可以很灵活的对待二者的关系。

      Apple Script 最大的优势是可以操作利用 macOS 的 GUI 界面,如点击某个菜单栏项目,模拟按下某个键盘按键等。

      Shell Script 的优势是,有非常多的 CUI(命令行界面)的程序可以使用;另外,Python 脚本、Ruby 脚本等等其实都是 Shell Script,区别就在于第一行中 Shebang 指定的 interpreter(解释程序)不一样,如 #!/usr/bin/perl 就是 Perl 脚本。

      JavaScript 在这里是比较特殊的存在,首先 macOS 有着一套 JavaScript for Automation (JXA),所以用 JavaScript 可以实现 Apple Script 的功能,另外 LaunchBar(Alfred 也是)对 JavaScript 有特殊照顾,一些特殊的行为,如,使 LaunchBar 发出 alert、使 LaunchBar 运行某个特定的 action,都只能通过 JavaScript 实现。

      —— Oscar Gong
      2017年11月02日 1
  • 郝海龙
    非常用好,解决了一直以来的痛点。
    2017年11月01日