How can I programmatically run terminal command?
Now I'm doing like this:
-(IBAction)proceedTapped:(id)sender
{
NSLog(#"%#",[self runCommand:#"cd ~"]);
NSLog(#"%#",[self runCommand:#"ls"]);
}
-(NSString *)runCommand:(NSString *)commandToRun
{
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
NSArray *arguments = [NSArray arrayWithObjects:
#"-c" ,
[NSString stringWithFormat:#"%#", commandToRun],
nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *output;
output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
return output;
}
For single commands this code works well, but in my case, when I want to change directory
to ~(home) and then do 'ls' this doesn't work well (it looks like to run two commands in two different terminal windows).
So how to run multiple commands like in one terminal window ?
Thank you.
In one of my applications I have:-
- (IBAction)openDirInTerminal:(id)sender { // context only
DirectoryItem *item = (DirectoryItem *)[self.dirTree focusedItem];
NSString *s = [NSString stringWithFormat:
#"tell application \"Terminal\" to do script \"cd \'%#\'\"", item.fullPath];
NSAppleScript *as = [[NSAppleScript alloc] initWithSource: s];
[as executeAndReturnError:nil];
}
DirectoryItem *item = (DirectoryItem *)[self.dirTree focusedItem]; is my method, but replace item.fullPath with a Path.
You could add the 2nd command to the script string (followed by a newline).
Related
I want to make cocoa app execute .sh file or other Operation,
this my code:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#",[self cmd:#"cd Desktop;ls;"]);
}
- (NSString *)cmd:(NSString *)cmd
{
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/bash"];
NSArray *arguments = [NSArray arrayWithObjects: #"-c", cmd, nil];
[task setArguments: arguments];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task launch];
NSData *data = [file readDataToEndOfFile];
return [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
}
but log error:
ls: .: Operation not permitted
how to do that?I search about macOS permit,Do I need use SMJobBless ?
Sandbox applications aren't allowed to read outside the application folder. So in order for your script to work you need to turn off Sandbox.
Also you need to change the path like Sangram S. mentioned or set the current directory to the home folder:
[task setCurrentDirectoryPath:NSHomeDirectory()];
change
NSLog(#"%#",[self cmd:#"cd Desktop;ls;"]);
with
NSLog(#"%#",[self cmd:#"cd ~/Desktop; ls;"]);
I can run an executable from a known local directory within a Cocoa app like this:
// Run the server.
NSTask *task = [[NSTask alloc] init];
NSPipe *pipe = [NSPipe pipe];
NSString* scriptPath = #"/Users/example/Server/runServerExecutable.sh";
[task setLaunchPath: #"/bin/sh"];
[task setArguments: [NSArray arrayWithObjects: scriptPath, nil]];
[task setStandardOutput: pipe];
[task launch];
Could anyone help me on these questions?
Where should I include the executable/script/text files in the app bundle?
How to modify scriptPath to run the script programmatically?
Thanks a lot!
Drag and drop the script/text files to your xcode project -> Project Navigator, so that it will get added to your project. Build the project. Open the Bundle, you will be able to see the added file in Resources directory.
Now, the code given below will help you get the file from the resources. For the sake of example, I have added a script by the name "OpenSafari.sh"
NSTask *temp = [[NSTask alloc] init];
[temp setLaunchPath:#"/bin/sh"];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"OpenSafari" ofType:#"sh"];
NSArray *tempargs = [NSArray arrayWithObjects:filePath,nil];
[temp setArguments:tempargs];
NSPipe *temppipe = [NSPipe pipe];
[temp setStandardOutput:temppipe];
NSPipe *errorPipe = [NSPipe pipe];
[temp setStandardError:errorPipe];
[temp launch];
NSData *data = [[temppipe fileHandleForReading] readDataToEndOfFile];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *dataErr = [[errorPipe fileHandleForReading] readDataToEndOfFile];
NSString *resultErr = [[NSString alloc] initWithData:dataErr encoding:NSUTF8StringEncoding];
Hope this helps!
I have a Mac (not iOS) application. I want to run a shell command 'find' after the user selects a folder with NSOpenPanel. The following is what I have.
NSString *path = [url path];
NSString *folderName = [path lastPathComponent];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/usr/bin/find"];
NSMutableString *command = [[NSMutableString alloc] initWithString:path];
[command appendString:#" -name '._*' -type f "];
NSArray* args = [NSArray arrayWithObjects:#"commit",command,nil];
[task setArguments:args];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
[task launch];
NSFileHandle *file;
file = [pipe fileHandleForReading];
NSData *data;
data = [file readDataToEndOfFile];
NSString *output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"%#",output);
It's my first time running a shell command with a Mac application that is developed with Objective-C. I suppose that I'm on the right track. Anyway, when I select a folder, I get the following debugger output message.
find: commit: No such file or directory
find: find: /Volumes/SDHC 16 GB/More -name '._*' -type f : No such file or directory
I suppose that the shell command cannot read this sort of file paths. Do I need to convert it into a shell path or whatever it understand? If so, how?
Thank you for your advice.
I got it.
NSString *path = [url path];
NSString *folderName = [path lastPathComponent];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/usr/bin/find"];
NSMutableString *command = [[NSMutableString alloc] initWithString:#""];
[command appendString:#" -name '._*' -type f"];
NSArray* args = [NSArray arrayWithObjects:path,command,nil];
[task setArguments:args];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
[task launch];
NSFileHandle *file;
file = [pipe fileHandleForReading];
NSData *data;
data = [file readDataToEndOfFile];
NSString *output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"%#",output);
In my program I currently use NSTask 5 times, and it all works very well, but I'm tired of having to repeat so much code when it's all so similar, so I tried putting it in a function. Unfortunately it results in a crash on the line: [task launch]. Other than that I can't figure out what's causing the crash as if I use this code outside the function it works perfectly.
The method I am using is as follows:
- (NSString *)performTask: (NSString *)launchPath: (NSString *)argument1: (NSString *)argument2: (NSString *)argument3: (NSString *)argument4: (NSString *)argument5
{
NSString *resPath = [[NSBundle mainBundle] resourcePath];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: [NSString stringWithFormat: launchPath, resPath]];
NSArray *arguments = [NSArray arrayWithObjects: argument1, argument2, argument3, argument4, argument5, nil];
[task setArguments: arguments];
NSPipe *pipe = [NSPipe pipe];
[task setStandardInput:[NSPipe pipe]];
[task setStandardOutput: pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task launch];
NSData *data = [file readDataToEndOfFile];
NSString *status = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
return status;
}
I really hope this can be fixed, I really cannot see why this crashes.
Thanks in advance everyone.
Check this out it's pretty cool I use it:
https://gist.github.com/1875386
It's also much easier than using arrayWithObjects: for NSTask...
rc
I'm trying to call ffmpeg from NSTask in objective-c. I execute the ffmpeg command in terminal and it works flawlessly every time. I make the same command using NSTask, and it never gives me the whole output. It cuts it off half way through the output, at a seemingly random spot every time. Here is my code.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSString* ffmpegPath = [[NSBundle mainBundle] pathForResource:#"ffmpeg" ofType:#""];
NSString* path = #"test.mov";
NSTask *task = [[NSTask alloc] init];
NSArray *arguments = [NSArray arrayWithObjects: #"-i", path, nil];
NSPipe *pipe = [NSPipe pipe];
NSFileHandle * read = [pipe fileHandleForReading];
[task setLaunchPath: ffmpegPath];
[task setArguments: arguments];
[task setStandardOutput: pipe];
[task launch];
[task waitUntilExit];
NSData* data = [read readDataToEndOfFile];
NSString* stringOutput = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", stringOutput);
NSLog(#"%i", [task terminationStatus]);
NSLog(#"DONE");
}
And just like that I figured it out. Apparently the output had non UTF8Characters in it. Switched it over to NSASCIIStringEncoding and voila. Magic.