繁体   English   中英

如何从任何目录快速运行终端命令?

[英]How to run terminal command in swift from any directory?

我正在尝试创建一个涉及允许用户运行终端命令的 macOS 应用程序。 我能够运行命令,但据我所知,它是从我的应用程序内的目录运行的。 运行pwd返回/Users/<me>/Library/Containers/<My app's bundle identifier>/Data

如何选择命令运行的目录?

我也在寻找一种让cd工作的方法,但如果我可以选择运行终端命令的目录,我可以手动处理cd

这是我目前用于运行终端命令的代码:

func shell(_ command: String) -> String {
    let task = Process()
    let pipe = Pipe()

    task.standardOutput = 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
    
}

我在 Big Sur 上使用 Xcode 12。

谢谢!

Process上有一个已弃用的属性currentDirectoryPath

假设您不想使用已弃用的属性,请在阅读其文档后转到FileManager并查看管理当前目录及其含义的规定。

或者只是像您考虑的那样使用cd - 您正在启动一个 shell ( zsh ),并将shell 命令行作为参数。 命令行可以包含多个由分号分隔的命令,因此您可以在command值前添加cd

后一种方法避免更改当前进程的当前目录。

HTH

要添加到 CRD 的答案中,如果使用cd方法,您还可以考虑使用&&分隔您的命令,以等待先前的命令成功完成,然后再继续执行依赖于它的下一个命令。

尝试您希望在终端中运行的命令,看看它是否按预期完成

例如: /bin/bash -c "cd /source/code/ && git pull && swift build"

如果一切正常,您可以继续在您的 swift 代码中使用它,如下所示:
shell("cd /source/code/ && git pull && swift build")


关于弃用的主题,您可能希望将 launchPath 替换为executableURL并将 launch() 替换为run()

带有更新代码的示例实现:

@discardableResult
func shell(_ args: String...) -> Int32 {
    let task = Foundation.Process()
    
    task.executableURL = URL(fileURLWithPath: "/bin/bash")
    task.arguments = ["-c"]
    task.arguments = task.arguments! + args
    
    //Set environment variables
    var environment = ProcessInfo.processInfo.environment
    environment["PATH"]="/usr/bin/swift"
    //environment["CREDENTIALS"] = "/path/to/credentials"
    task.environment = environment
    
    let outputPipe = Pipe()
    let errorPipe = Pipe()
    
    task.standardOutput = outputPipe
    task.standardError = errorPipe
    
    do {
        try task.run()
    } catch {
        // handle errors
        print("Error: \(error.localizedDescription)")
    }
    task.waitUntilExit()
    
    let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
    let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
    
    let output = String(decoding: outputData, as: UTF8.self)
    let error = String(decoding: errorData, as: UTF8.self)
    
    //Log or return output as desired
    print(output)
    print("Ran into error while running: \(error)")
    
    return task.terminationStatus
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM