Skip to content

Commit 8675701

Browse files
committed
Support shelling out to a series of commands, optionally at a given path
This addition to ShellOut makes it easier to run a series of commands, without having to manually string them together using ‘&&’. It also enables you to easily run a shell command at a given path, without having to ‘cd’ to it first.
1 parent 07f32cd commit 8675701

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

Sources/ShellOut.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,39 @@ import Foundation
1313
*
1414
* - parameter command: The command to run
1515
* - parameter arguments: The arguments to pass to the command
16+
* - parameter path: The path to execute the commands at (defaults to current folder)
1617
*
1718
* - returns: The output of running the command
1819
* - throws: `ShellOutError` in case the command couldn't be performed, or it returned an error
1920
*
2021
* Use this function to "shell out" in a Swift script or command line tool
21-
* For example: `shellOut(to: "mkdir", arguments: ["NewFolder"])`
22+
* For example: `shellOut(to: "mkdir", arguments: ["NewFolder"], at: "~/CurrentFolder")`
2223
*/
23-
@discardableResult public func shellOut(to command: String, arguments: [String] = []) throws -> String {
24+
@discardableResult public func shellOut(to command: String,
25+
arguments: [String] = [],
26+
at path: String = ".") throws -> String {
2427
let process = Process()
25-
let command = "\(command) \(arguments.joined(separator: " "))"
28+
let command = "cd \"\(path)\" && \(command) \(arguments.joined(separator: " "))"
2629
return try process.launchBash(with: command)
2730
}
2831

32+
/**
33+
* Run a series of shell commands using Bash
34+
*
35+
* - parameter commands: The commands to run
36+
* - parameter path: The path to execute the commands at (defaults to current folder)
37+
*
38+
* - returns: The output of running the command
39+
* - throws: `ShellOutError` in case the command couldn't be performed, or it returned an error
40+
*
41+
* Use this function to "shell out" in a Swift script or command line tool
42+
* For example: `shellOut(to: ["mkdir NewFolder", "cd NewFolder"], at: "~/CurrentFolder")`
43+
*/
44+
@discardableResult public func shellOut(to commands: [String], at path: String = ".") throws -> String {
45+
let command = commands.joined(separator: " && ")
46+
return try shellOut(to: command, at: path)
47+
}
48+
2949
// Error type thrown by the `shellOut()` function, in case the given command failed
3050
public struct ShellOutError: Swift.Error {
3151
/// The error message that was returned through `STDERR`

Tests/ShellOutTests/ShellOutTests.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,35 @@ class ShellOutTests: XCTestCase {
2323
XCTAssertEqual(echo, "Hello world")
2424
}
2525

26+
func testSingleCommandAtPath() throws {
27+
try shellOut(to: "echo \"Hello\" > \(NSTemporaryDirectory())ShellOutTests-SingleCommand.txt")
28+
29+
let textFileContent = try shellOut(to: "cat ShellOutTests-SingleCommand.txt",
30+
at: NSTemporaryDirectory())
31+
32+
XCTAssertEqual(textFileContent, "Hello")
33+
}
34+
35+
func testSeriesOfCommands() throws {
36+
let echo = try shellOut(to: ["echo \"Hello\"", "echo \"world\""])
37+
XCTAssertEqual(echo, "Hello\nworld")
38+
}
39+
40+
func testSeriesOfCommandsAtPath() throws {
41+
try shellOut(to: [
42+
"cd \(NSTemporaryDirectory())",
43+
"mkdir -p ShellOutTests",
44+
"echo \"Hello again\" > ShellOutTests/MultipleCommands.txt"
45+
])
46+
47+
let textFileContent = try shellOut(to: [
48+
"cd ShellOutTests",
49+
"cat MultipleCommands.txt"
50+
], at: NSTemporaryDirectory())
51+
52+
XCTAssertEqual(textFileContent, "Hello again")
53+
}
54+
2655
func testThrowingError() {
2756
do {
2857
try shellOut(to: "cd", arguments: ["notADirectory"])

0 commit comments

Comments
 (0)