{"id":7,"date":"2008-03-05T23:21:16","date_gmt":"2008-03-05T23:21:16","guid":{"rendered":"http:\/\/vgable.com\/blog\/2008\/03\/05\/calling-the-command-line-from-cocoa\/"},"modified":"2009-11-29T23:50:09","modified_gmt":"2009-11-30T04:50:09","slug":"calling-the-command-line-from-cocoa","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2008\/03\/05\/calling-the-command-line-from-cocoa\/","title":{"rendered":"Calling the Command Line from Cocoa"},"content":{"rendered":"<p>The best way to call a shell-command from Coca is by using an <a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Reference\/Foundation\/Classes\/NSTask_Class\/Reference\/Reference.html\">NSTask<\/a>.  Here are the three resources on using an NSTask that I found the most helpful:<br \/>\n<a href=\"http:\/\/www.cocoadev.com\/index.pl?NSTask\">CocoDev&#8217;s write up<\/a><br \/>\n<a href=\"http:\/\/www.borkware.com\/quickies\/one?topic=NSTask\">A few quick exaples<\/a><br \/>\n<a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Reference\/Foundation\/Classes\/NSTask_Class\/Reference\/Reference.html\">NSTask Class Refrence<\/a><\/p>\n<p><a href=\"http:\/\/www.vgable.com\/code\/ShellTask.zip\">And here is some sample code to do it for you.<\/a>  You are free to use this code however you please, but attribution is always appreciated.  The two principle functions are:<\/p>\n<p><code>+ (NSString*) executeShellCommandSynchronously:(NSString*)command<\/code> executes the command &#8220;command&#8221; with <a href=\"http:\/\/en.wikipedia.org\/wiki\/Bourne_shell\">sh<\/a>, wait until it finishes, and return whatever it printed to stdout and stderr as an NSString.<br \/>\nCAUTION: may deadlock under some circumstances if the output gets so big it fills the pipe.  See <a href=\"http:\/\/dev.notoptimal.net\/search\/label\/NSTask\"> http:\/\/dev.notoptimal.net\/search\/label\/NSTask<\/a> for an overview of the problem, and a solution.  I have not experienced the problem myself, so I can&#8217;t comment.<\/p>\n<p><code>executeShellCommandAsynchronously:<\/code> will have <a href=\"http:\/\/en.wikipedia.org\/wiki\/Bourne_shell\">sh<\/a> execute <code>command<\/code> in the background, without blocking anything.<\/p>\n<p>For quick hacks, the POSIX <a href=\"http:\/\/www.hmug.org\/man\/3\/system.php\"><code>int system(const char* command)<\/code><\/a> function, might be a good one-line solution.  It synchronously evaluates <code>command<\/code> with <a href=\"http:\/\/en.wikipedia.org\/wiki\/Bourne_shell\">sh<\/a>.<\/p>\n<p>Enjoy!<\/p>\n<p>EDITED 2009-11-29: this code probably <em>won&#8217;t<\/em> have the same <code>$PATH<\/code> you would get if you used Terminal. See <a href=\"http:\/\/stackoverflow.com\/questions\/386783\/nstask-not-picking-up-the-expected-path-from-the-users-environment\/1817870#1817870\">this question on stackoverflow<\/a> for more details. A solution that seems to work is to do,<\/p>\n<pre>\n    [task setLaunchPath:@\"\/bin\/bash\"];\n    NSArray\t*args = [NSArray arrayWithObjects:@\"-l\",\n    \t\t\t\t @\"-c\",\n    \t\t\t\t <strong>commandlineHere<\/strong>,\n    \t\t\t\t nil];\n    [task setArguments: args];\n<\/pre>\n<p>This launches <code>bash<\/code> (<em>not<\/em> in <code>sh<\/code> compatibility mode), and -l (lowercase L) tells it to  &#8220;act as if it had been invoked as a login shell&#8221;. I haven&#8217;t tested this on systems where <code>bash<\/code> isn&#8217;t the default shell. There are lots of ways <code>$PATH<\/code> could be set, and I haven&#8217;t tested them all. But you are almost certainly going to be OK if everything you refer to is in <code>\/usr\/bin:\/bin:\/usr\/sbin:\/sbin<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The best way to call a shell-command from Coca is by using an NSTask. Here are the three resources on using an NSTask that I found the most helpful: CocoDev&#8217;s write up A few quick exaples NSTask Class Refrence And here is some sample code to do it for you. You are free to use [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,3,5,4,10,9],"tags":[199,613,86,197,407],"class_list":["post-7","post","type-post","status-publish","format-standard","hentry","category-cocoa","category-macosx","category-objective-c","category-programming","category-tips","category-unix","tag-bash","tag-c","tag-command-line","tag-nstask","tag-sh"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/comments?post=7"}],"version-history":[{"count":2,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/7\/revisions"}],"predecessor-version":[{"id":516,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/7\/revisions\/516"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=7"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=7"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}