使用 swift 在 MacOS 中执行位于应用程序包中的 shell 脚本

executing a shell script located in app bundle in MacOS with swift

我想知道是否可以在 swift 中执行位于我的应用程序包中的 shell 脚本。这是一个禁用沙盒的 Mac 应用程序。

这就是我获得 url 的方式,它正在运行:

guard let saveScriptURL = Bundle.main.url(forResource: "scripts/save", withExtension: "sh") else {
            VsLogger.logDebug("***", "Unable to get save.sh file")
            return false
        }

哪个returns这个

/Users/me/Library/Developer/Xcode/DerivedData/appName-fcowyecjzsqnhrchpnwrtthxzpye/Build/Products/Debug/appName.app/Contents/Resources/scripts/save.sh

然后这是我的代码运行它。

  func shell(_ scriptURL: URL) throws {
        let task = Process()
        let pipe = Pipe()
        task.standardOutput = pipe
        task.standardError = pipe
        task.executableURL =  scriptURL
        try task.run()
    }

但我收到错误:

Error Domain=NSCocoaErrorDomain Code=4 "The file “save.sh” doesn’t exist." UserInfo={NSFilePath=/Users/me/Library/Developer/Xcode/DerivedData/appName-fcowyecjzsqnhrchpnwrtthxzpye/Build/Products/Debug/appName.app/Contents/Resources/scripts/save.sh}

不胜感激。

您的代码存在一些问题需要修复。

首先你错误地使用了 Process,属性 executableURL 用于可执行文件,在这种情况下是 shell,你想用于 运行ning 你的脚本,所以对于 zsh 它应该设置为

task.executableURL = URL(fileURLWithPath: "/bin/zsh")

其次,经过反复试验,我们似乎无法直接执行脚本,我认为这是因为即使我们使用 chmod 将脚本设置为可执行文件,当脚本被复制到包中时,它也会丢失。所以脚本需要 运行 as "source save.sh"

要将脚本设置为 运行,我们使用 arguments 属性

task.arguments = ["-c", "source \(scriptURL.path"]

所以你的 shell 函数就变成了

func shell(_ scriptURL: URL) throws {
    let task = Process()
    let pipe = Pipe()
    task.standardOutput = pipe
    task.standardError = pipe

    task.executableURL = URL(fileURLWithPath: "/bin/zsh")
    task.arguments = ["-c", "source \(scriptURL.path)"]
    try task.run()
}