Trying to run simple Bash command in Swift - 'Couldn't posix_spawn: error 13' - swift

I'm trying to build a MacOS app that can run bash commands from GUI input and have fallen at the first hurdle. I've been using this question's answer as a reference but it doesn't seem to work for me. This is my code:
import Foundation
#IBAction func buttonClicked(_ sender: Any) {
shell("ls")
}
#discardableResult
func shell(_ args: String...) -> Int32 {
let task = Process()
task.launchPath = "/Users/myUser/desktop"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
I've seen others asking about this error but they are getting it for slightly different reasons meaning I can't seem to find a fix for my particular instance of the problem.
Any ideas?
EDIT - Would also be great if someone could give me a hint as to how to get the output of the ls command back into my program, to store as a string for example.

For a simple terminal app this is what I used
func shell(_ command: String) -> String {
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
guard let output = String(data: data, encoding: .utf8) else {
print("Failed to produce string from \(data)")
abort()
}
return output
}

Related

How to show real time result while using terminal command in a swift script

I am using Xcode Project Renamer to rename my Xcode project, after that I used the code below to install pod file.
It's working good but the terminal showing result after pod installed. I want to show result while installing the pod.
#discardableResult
private func shell(_ command: String) -> String {
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
// pipe.fileHandleForReading.readDataToEndOfFile()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
return output
}
let command = shell("pod install")
print(command)
Can someone help please.

executing system_profiler via swift

Wanting to get a details of all installed applications by executing system_profiler SPApplicationsDataType
The snippet given below works just fine in playground, however gives me code signing internal problem: unexpected error from xpc when I try executing it from an application.
func shell(_ command: String) -> String {
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
return output
}
print(shell("system_profiler SPApplicationsDataType"))
P.S Apologies if this is a dumb question, I'm fairly new to swift and xcode technologies :)

swift process standart input pipe

I want to create an encrypted .dmg on macOS using swift
I haven't found an implementation for hdiutil, so I'm forced to use terminal commands for that.
Unfortunately, I don't know how to work with pipes (which should be used regarding apples documentation)
The command i want to trigger is the following:
printf 'password' | hdiutil create -encryption AES-256 -volname backupname -stdinpass -size 1GB backupname.dmg
The code, I've tried is the following (nothing worked):
func shell(_ args: String...) -> Int32 {
let task = Process()
let inputpipe = Pipe()
task.standardInput = inputpipe
//1. try: inputpipe.fileHandleForReading.write("password".data(using: .utf8)!)
//2. try: inputpipe.fileHandleForWriting.write("password".data(using: .utf8)!)
/*3. try: inputpipe.fileHandleForWriting.writeabilityHandler = {
pipe in
let inputString = "password"
let data = inputString.data(using: .utf8)!
pipe.write(data)
}*/
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
print(shell("hdiutil", "create", "-encryption", "AES-256", "-volname", "backupname", "-stdinpass", "-size", "1MB", "~/Documents/backupname.dmg"))
How do i correctly provide the password using Process()

Swift + terminal

I'm looking for a way to run terminal commands from in Swift (macOS). I came accross this post, but I can't seem to get any of the solutions to work. I am trying to shut down my mac from my app as you can do from terminal (osascript -e 'tell app "loginwindow" to «event aevtrsdn»'), but whenever I do it, I get error: Couldn't posix_spawn: error 13.
I am using this code:
func shell(launchPath: String, arguments: [String] = []) -> (String? , Int32) {
let task = Process()
task.launchPath = launchPath
task.arguments = arguments
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()
return (output, task.terminationStatus)
}
and I call it from this:
let z = shell(launchPath: "/usr/bin/osascript", arguments: ["-e", "\'tell app \"loginwindow\" to «event aevtrsdn»\'"])
Any help?
Your code is correct, but you must not enclose the second argument
in single-quotes:
let z = shell(launchPath: "/usr/bin/osascript", arguments: ["-e", "tell app \"loginwindow\" to «event aevtrsdn»"])
That is only necessary when executing a program from the shell.
Process passes the given arguments directly to the spawned executable,
without interpretation by a shell.

How to use Process() in Swift 3 for Linux?

The following function executes a process in Swift 3 on macOS. But if I run the same code in Ubuntu I get the error that Process is an unresolved identifier.
How do I run a process / task in Swift 3 for Ubuntu and get its output?
import Foundation
// runs a Shell command with arguments and returns the output or ""
class func shell(_ command: String, args: [String] = []) -> String {
let task = Process()
task.launchPath = command
task.arguments = args
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String? = String(data: data,
encoding: String.Encoding.utf8)
task.waitUntilExit()
if let output = output {
if !output.isEmpty {
// remove whitespaces and newline from start and end
return output.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
return ""
}
I cannot test it myself currently, but according to the source code
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSTask.swift,
the corresponding class is (still) called Task on Linux, not Process
as on Apple platforms.