在 swift 脚本中运行 shell 命令

时间:2021-07-08 10:59:33

标签: swift shell zsh

我正在寻找一种在 Swift 脚本中运行 shell 命令的解决方案。

这是我的代码:

func shellEnv(_ command: String) -> String {
    let task = Process()
    let pipe = Pipe()
    
    task.standardOutput = pipe
    task.standardError = pipe
    task.arguments = ["-c", command]
    task.launchPath = "/bin/zsh"
    task.launch()
    
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8)!
    
    return output
}

它适用于内置命令,但不能处理诸如“brew”、“node”和其他手动安装的命令之类的命令。

那我该如何解决呢?

1 个答案:

答案 0 :(得分:2)

您需要为 PATH 设置 task 环境变量。这已在您的终端中设置,这就是为什么您可以直接执行 brewnode 以及其他很酷的事情,而无需指定它们的完整路径。

您可以通过执行以下操作来查看终端中的设置:

echo $PATH

它会打印出类似的东西(对我来说它还有很多东西。这只是摘录):

/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

如果您复制并粘贴 echo $PATH 的整个输出,并将其放入 environmenttask 属性中,那么您将能够在 swift 脚本中使用相同的命令就像在您的终端中一样。

task.environment = ["PATH": "<paste the output here>"]

正如 Alexander 在 comments 中所说,另一种方法是添加 l 选项。这是一个 MCVE:

#!/usr/bin/swift

// main.swift
import AppKit

func shellEnv(_ command: String) -> String {
    let task = Process()
    let pipe = Pipe()
    
    task.standardOutput = pipe
    task.standardError = pipe
    task.arguments = ["-cl", command]
    task.launchPath = "/bin/zsh"
    task.launch()
    
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8)!
    
    return output
}

print(shellEnv("brew list")) // assuming you have brew

要运行,chmod +x main.swift 然后 ./main.swift,您将看到列出的所有自制软件包。

相关问题