Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chaining shell commands with pipe in a Swift script

I'm trying to chain shell command together in a Swift script. The actual commands in question are the output of gource piped to the input of ffmpeg, but here's a simplified, contrived example of what I'm trying to do:

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")

Expected output:

foo
bar
baz

Actual output:

foo
bar
baz
baz | uniq

The | is being interpreted as part of the last argument. How can I chain commands together, so that data flows from one to the next, in a Swift script? I tried various combinations of assigning standardIn and standardOut and using Pipe() between two Processes, but either I'm doing it wrong, or I'm not connecting the right pieces together.

like image 774
Zev Eisenberg Avatar asked Jan 18 '17 04:01

Zev Eisenberg


1 Answers

I got an answer with help from 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")
like image 97
Zev Eisenberg Avatar answered Nov 09 '22 11:11

Zev Eisenberg