Reputation: 1069
I've read solutions for doing this using NSTask: they all look very very long... So I managed to do the exact same thing using this code (which gets both standard output and standard error):
NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:@[ @"-c", @"aCommand"]];
NSString *stringToRemove = [task description];
[task launch];
NSString *output = [[task description] stringByReplacingOccurrencesOfString:stringToRemove withString:@""];
Are there any drawbacks using this solution? Is there a shorter way to filter the output?
Upvotes: 0
Views: 965
Reputation: 606
If your goal is just to run a command and wait for it to exit (for example to grab information from a shell command in a CLI application), you can use the following (ARC enabled):
// Start the task with path and arguments.
NSTask* task = [NSTask new];
[task setExecutableURL:[NSURL fileURLWithPath:@"/path/to/task"]];
[task setArguments:@[@"your", @"arguments", @"here"]];
// Intercept the standard output of the process.
NSPipe* output = [NSPipe pipe];
[task setStandardOutput:output];
// Launch and wait until finished.
[task launch];
[task waitUntilExit];
// Read all data from standard output as NSData.
NSData* resultData = [[output fileHandleForReading] readDataToEndOfFile];
// Convert NSData to string (could be combined with above when ARC used).
NSString* result = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
This doesn't seem unreasonable in length (and could probably be shortened, though I left this in for readability), and if you're using this often you could abstract it into a function.
I also noticed that, as you don't redirect the output in your code, it would also print the output to the console, which might be unintended.
Upvotes: 0
Reputation: 162712
Are there any drawbacks using this solution? Is there a shorter way to filter the output?
Yes, many drawbacks. You are relying on an implementation detail that description
will magically return the task's command line and output. That is not claimed by the documentation nor is description
really acceptable to use beyond debugging/logging.
I.e. that code only works by convenience.
But that code isn't really working. If the command you were to run never exits or takes a while to run or produces a massive amount of output, then that code is likely to not actually grab any of the output at all or to spew truncated output.
There is a reason why the examples that use NSTask
tend to be a bit lengthy. Managing I/O between processes is actually quite hard and there are a lot of different options that need to be taken into account.
Upvotes: 3