在Swift脚本中使用管道链接shell命令

时间:2017-01-18 04:34:03

标签: swift shell scripting

我试图在Swift脚本中将shell命令链接在一起。有问题的实际命令是gource输出到ffmpeg输入的输出,但这是我尝试做的一个简化的,人为的例子:

let echo = Process()

echo.launchPath = "/usr/bin/env"
echo.arguments = ["echo", "foo\nbar\nbaz\nbaz", "|", "uniq"]

let pipe = Pipe()
echo.standardOutput = pipe

echo.launch()
echo.waitUntilExit()

// Get the data
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)

print(output ?? "no output")

预期产出:

foo
bar
baz

实际输出:

foo
bar
baz
baz | uniq

|被解释为最后一个参数的一部分。如何将命令链接在一起,以便数据在Swift脚本中从一个流向下一个?我尝试了在两个standardIn之间分配standardOutPipe()以及使用Process的各种组合,但要么我做错了,要么我做了没有将正确的部分连接在一起。

3 个答案:

答案 0 :(得分:8)

我在zadr的帮助下得到了答案:

import Foundation

let pipe = Pipe()

let echo = Process()
echo.launchPath = "/usr/bin/env"
echo.arguments = ["echo", "foo\nbar\nbaz\nbaz"]
echo.standardOutput = pipe

let uniq = Process()
uniq.launchPath = "/usr/bin/env"
uniq.arguments = ["uniq"]
uniq.standardInput = pipe

let out = Pipe()
uniq.standardOutput = out

echo.launch()
uniq.launch()
uniq.waitUntilExit()

let data = out.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)

print(output ?? "no output")

答案 1 :(得分:0)

对于可能遇到同样问题的其他人,这是我从Zev的答案中得出的适合创建SHA1 HMAC哈希的内容:

func getHMAC(forValue value: String, key: String) -> String {

    let pipe = Pipe()

    let echo = Process()
    echo.launchPath = "/usr/bin/env"
    echo.arguments = ["echo", "-n", value]
    echo.standardOutput = pipe

    let task = Process()
    task.launchPath = "/usr/bin/env"
    task.arguments = ["openssl", "sha1", "-hmac", key]
    task.standardInput = pipe

    let output = Pipe()
    task.standardOutput = output

    echo.launch()
    task.launch()
    task.waitUntilExit()

    let data = output.fileHandleForReading.readDataToEndOfFile()
    return NSString(data: data, encoding: String.Encoding.utf8.rawValue) as! String
}

当从Swift脚本进行简单的API调用时,这非常有用,这些脚本需要HTTP标头中的哈希。据我所知,这是唯一可行的方式(因为我们无法在Swift脚本中使用Objective-C CommonCrypto框架)

答案 2 :(得分:-1)

您应该看看这个。这是通过链接进行管道传输的简单方法的示例。 https://gist.github.com/eahrold/b5c5fd455225a8726e1cc31708e139db

所以您可以像

 let ls = Process("/bin/ls", ["-al"])
 let grep = Process("/usr/bin/grep", ["com"])
 let cut = Process("/usr/bin/awk", ["{print $3}"])

 ls.pipe(grep).pipe(cut).complete {
    message, status in
    print("Your results: \(message)")
 }
 ls.launch()