Home > Software design >  Call Process with arguments in Swift macOS App
Call Process with arguments in Swift macOS App

Time:01-11

I'm trying to run a Process from my Swift macOS app. But, I'm having trouble formatting the arguments to my Process.

So far, the following code is working well:

let task = Process()
var environment =  ProcessInfo.processInfo.environment
environment["PATH"] = "/usr/local/bin"
task.environment = environment
task.currentDirectoryPath = "/usr/local/bin"
task.executableURL = URL(fileURLWithPath: "/usr/local/bin/convert")
task.arguments = [filename, filename ".pdf"]
            
let outputPipe = Pipe()
let errorPipe = Pipe()
task.standardOutput = outputPipe
task.standardError = errorPipe
...
try! task.run()

When I try and add the arguments "-trim", "-fuzz 10%" to the existing task.arguments the program crashes. The process error is:

New error: convert: unrecognized option `-fuzz 10%' @ error/convert.c/ConvertImageCommand/1718.

How do I properly format these arguments to run the process?

CodePudding user response:

When you run commands on the command line, your shell typically splits arguments to pass to a program by whitespace — when you run a command like

/usr/local/bin/convert -trim -fuzz 10% <input> <output>

the shell will split those arguments and pass them along to convert like so:

["/usr/local/bin/convert", "-trim", "-fuzz", "10%", "<input>", "<output>"]

When convert goes to parse the arguments you pass in, it iterates over those arguments and attempts to match them against a known list that it accepts. It looks up -trim, which it recognizes, and -fuzz, which it recognizes, and it accepts 10% as the argument to -fuzz... and so on.

When you execute a program directly from your code, whether through Process, or the lower level execve or posix_spawn, the arguments that you pass in are forwarded directly to the receiving process. In your original case, this means that convert received:

["/usr/local/bin/convert", "-trim", "-fuzz 10%", "<input>", "<output>"]

convert, and many other programs, don't further split up arguments on whitespace themselves, so when it tried to match the entirety of -fuzz 10% as a single command line option (space and all), it couldn't find anything.

This is equivalent to running

/usr/local/bin/convert -trim "-fuzz 10%" <input> <output>

on the command line, where the quotes prevent your shell from splitting words on whitespace. When I run that command locally on my machine, I get the exact same error:

convert: unrecognized option `-fuzz 10%' @ error/convert.c/ConvertImageCommand/1718.

The solution is to do the same splitting your shell might do, and pass in each argument separately as its own string:

task.arguments = ["-trim", "-fuzz", "10%", filename, filename ".pdf"]
  •  Tags:  
  • Related