3

Copied from How do I run an terminal command in a swift script? (e.g. xcodebuild) :

import Foundation

@discardableResult
func shell(_ args: String...) -> Int32 {
    let task = Process()
    task.launchPath = "/usr/bin/env"
    task.arguments = args
    task.launch()
    task.waitUntilExit()
    return task.terminationStatus
}

shell("ls")
shell("xcodebuild", "-workspace", "myApp.xcworkspace")

This looks neat. I am just wondering how environment variables like $PWD can be set for the process (named task here...).


I tried the following:

import Foundation

@discardableResult
func execCommand(_ args: String...) -> Int32 {
    let process = Process()
    process.launchPath = "/usr/bin/env"
    process.environment = ["PWD": "/Users"]
    if let env = process.environment {
        print(env["PWD"] ?? "Unknown")
    } else {
        print("Environment not available!")
    }
    process.arguments = args
    process.launch()
    process.waitUntilExit()
    return process.terminationStatus
}


execCommand("pwd")

And got these lines printed:

/Users
/private/tmp/AppIcon.appiconset

Apparently the environment variable has been set, but has no effect on the pwd command at all.


Another approach:

import Foundation

@discardableResult
func execCommand(_ args: String...) -> Int32 {
    let process = Process()
    process.launchPath = "/usr/bin/env"
    var environment = ProcessInfo.processInfo.environment
    environment["PWD"] = "/Users" //optionally set new vars, or overwrite old ones
    process.environment = environment
    if let env = process.environment {
        print(env["PWD"] ?? "Unknown")
    } else {
        print("Environment not available!")
    }
    process.arguments = args
    process.launch()
    process.waitUntilExit()
    return process.terminationStatus
}


execCommand("pwd")

Unfortunately same results as before.

Community
  • 1
  • 1
qed
  • 22,298
  • 21
  • 125
  • 196

1 Answers1

8

You just set the environment variable of the Process to a [String: String] containing the variable to value mappings.

let process = Process()
// ...
process.environment = ["home": "/Users/foo"]

If you want to pass on the current environment, you can do it like so:

let process = Process()
// ...
let environment = ProcessInfo.processInfo.environment
environment["home"] = "/Users/foo" //optionally set new vars, or overwrite old ones
process.environment = environment

If you want to set the working directory, that's not dictated by a environment variable, but rather, via the currentDirectoryPath property.

let process = Process()
// ...
process.currentDirectoryPath = "/Users"
Alexander
  • 59,041
  • 12
  • 98
  • 151