从Mac应用程序运行Swift命令

时间:2018-01-15 16:25:48

标签: swift xcode bash macos shell

我正在尝试使用基于Swift的Mac应用程序中的命令行运行Swift脚本。

我有以下类方法,它接受参数,并运行命令:

func shell(_ args: String...) -> Int32 {
    let task = Process()
    task.launchPath = "/usr/bin/env"
    task.arguments = args
    task.launch()
    task.waitUntilExit()
    return task.terminationStatus
}

我能够成功执行以下命令:

    shell("pwd")
    shell("ls")
    shell("swift")

pwd按预期返回应用程序构建目录中的所有文件。这包括我手动添加的hello.swift文件,它只打印“Hello,world!”。此外,运行swift确实授予对Swift环境的访问权限。

我运气不好的是运行如下命令:

shell("swiftc hello.swift")

相反,我收到以下错误:

env: swiftc hello.swift: No such file or directory

看起来我正面临着与这些帖子类似的情况:

Swift Process - execute command error

Running shell commands in Swift

但是,我不确定我是否完全理解其中对我的具体情况的所有影响。

1 个答案:

答案 0 :(得分:1)

为了澄清,在我们开始之前,swiftc用于将swift脚本编译成二进制文件。相反,使用swift脚本文件调用swift将解释给定文件。

  

env:swiftc hello.swift:没有这样的文件或目录

基本上,这表明env二进制文件正在传递两个参数: swiftc hello.swift 并且不知道该怎么做做它。

task.launchPath = "/usr/bin/env"

我不确定您为何在此处拨打env,但假设我正确理解了您的目标,我们可以使用bash来获得所需的结果。

我们假设我们有以下 script.swift 文件

#!/usr/bin/swift
import Foundation

func shell(_ args: String...) -> Int32 {
    let task = Process()
    task.launchPath = "/bin/bash"
    task.arguments = ["-c"]
    task.arguments = task.arguments! + args
    task.launch()
    task.waitUntilExit()
    return task.terminationStatus
}

_ = shell("pwd")
_ = shell( "swift cmds.swift")

不是拨打env,而是使用bash。为了将字符串传递给bash,它需要-c参数,我们在其前面加上

task.arguments = ["-c"]
task.arguments = task.arguments! + args

可以看到脚本的末尾调用文件 cmds.swift 。如果我们通过解释器执行 script.swift ,它将无法调用 cmds.swift - 本质上是从内部调用解释器!

因此,我们将 script.swift 编译为二进制文件:

swiftc script.swift

这将输出名为 script 的二进制文件。

正如我们所见,二进制文件调用 cmds.swift ,所以让我们使用以下脚本代码创建它...

#!/usr/bin/swift  
import Foundation

print("Hello World\n")

现在,如果我们执行我们编译的二进制文件,我们将看到它成功调用解释的脚本并输出路径(来自pwd)和&#34; Hello World&#34;来自调用< EM> cmds.swift