将 Shell 脚本转换为 *.app 文件
Converting a Shell Script Into a *.app File
使用 Automator.app 和 Platypus.app,我已经能够捆绑我创建的一个简单的 shell 脚本来在我的 MacBook Pro 上重新启动 wi-fi。生成的两个应用程序 运行 都正确,但有一个我想纠正的明显问题:应用程序从程序外部引用 shell 脚本。如何嵌入 shell 脚本并从应用程序的资源中引用它,以便应用程序可以 运行 即使原始源文件已移动?
顺便提一下,如果您在脚本上获取信息,您可以将其设置为使用终端打开。这将 运行 双击脚本。
否则,将脚本打包到 .app 包中是微不足道的。 Mac OS X 将愉快地 运行 任何识别为应用程序可执行文件的脚本。
至少,您需要以下结构:
- (姓名).app
- 内容
- MacOS
- (姓名)
其中名为 (name) 的文件是您的脚本(必须 是可执行的,并且 必须 有一个 shebang 行)。 (name) 在 .app 目录和脚本文件中必须相同:例如,如果您的应用程序目录名为 "My Shell Script.app",那么 MacOS 目录中的文件必须被调用"My Shell Script",无扩展名。
如果这样做不方便,可以使用 Info.plist 文件指定备用可执行文件名。 Info.plist 进入目录目录:
- Wrapper.app
- 内容
- Info.plist
- MacOS
- MyScript
如果您将 MyScript 指定为 属性 列表中的 CFBundleExecutable
,则此结构(包装器中名为 Wrapper.app 的 MyScript 可执行文件)有效:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>MyScript</string>
</dict>
</plist>
使用 Info.plist 文件可能更可取,因为这样可以在不破坏包装的情况下重命名它。
这是一个使用 /bin/sh
作为解释器的示例脚本,但您实际上可以拥有任何东西(#!/usr/bin/swift
、#!/usr/bin/python
等)。
#!/bin/sh
open -a Calculator
当您双击应用程序包时,脚本将 运行。
您可以在 Contents
目录中将您需要的任何其他内容与您的脚本捆绑在一起。如果您喜欢,可以使用 Resources
目录和类似的东西重现标准的可执行文件包布局。
虽然这有效,但似乎无法从脚本访问目录目录。它没有将环境变量传递给 bash 或我能找到的任何其他地方。这使得很难将内容捆绑到目录中,因为 bash 脚本似乎无法访问它。网上有各种 hack,但它们都涉及通过名称有效搜索脚本,这意味着如果在两个地方有两个版本的应用程序,那么它将失败。
有人解决了吗?
使用 Automator.app 和 Platypus.app,我已经能够捆绑我创建的一个简单的 shell 脚本来在我的 MacBook Pro 上重新启动 wi-fi。生成的两个应用程序 运行 都正确,但有一个我想纠正的明显问题:应用程序从程序外部引用 shell 脚本。如何嵌入 shell 脚本并从应用程序的资源中引用它,以便应用程序可以 运行 即使原始源文件已移动?
顺便提一下,如果您在脚本上获取信息,您可以将其设置为使用终端打开。这将 运行 双击脚本。
否则,将脚本打包到 .app 包中是微不足道的。 Mac OS X 将愉快地 运行 任何识别为应用程序可执行文件的脚本。
至少,您需要以下结构:
- (姓名).app
- 内容
- MacOS
- (姓名)
- MacOS
- 内容
其中名为 (name) 的文件是您的脚本(必须 是可执行的,并且 必须 有一个 shebang 行)。 (name) 在 .app 目录和脚本文件中必须相同:例如,如果您的应用程序目录名为 "My Shell Script.app",那么 MacOS 目录中的文件必须被调用"My Shell Script",无扩展名。
如果这样做不方便,可以使用 Info.plist 文件指定备用可执行文件名。 Info.plist 进入目录目录:
- Wrapper.app
- 内容
- Info.plist
- MacOS
- MyScript
- 内容
如果您将 MyScript 指定为 属性 列表中的 CFBundleExecutable
,则此结构(包装器中名为 Wrapper.app 的 MyScript 可执行文件)有效:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>MyScript</string>
</dict>
</plist>
使用 Info.plist 文件可能更可取,因为这样可以在不破坏包装的情况下重命名它。
这是一个使用 /bin/sh
作为解释器的示例脚本,但您实际上可以拥有任何东西(#!/usr/bin/swift
、#!/usr/bin/python
等)。
#!/bin/sh
open -a Calculator
当您双击应用程序包时,脚本将 运行。
您可以在 Contents
目录中将您需要的任何其他内容与您的脚本捆绑在一起。如果您喜欢,可以使用 Resources
目录和类似的东西重现标准的可执行文件包布局。
虽然这有效,但似乎无法从脚本访问目录目录。它没有将环境变量传递给 bash 或我能找到的任何其他地方。这使得很难将内容捆绑到目录中,因为 bash 脚本似乎无法访问它。网上有各种 hack,但它们都涉及通过名称有效搜索脚本,这意味着如果在两个地方有两个版本的应用程序,那么它将失败。 有人解决了吗?