Search code examples
bashescapingapplescript-objc

Is there a way to package bash shell scripts with AppleScriptObjC app on MacOSX with Xcode?


I am trying to automate three or four bash shell scripts using AppleScriptObjC as a wrapper. This will give me a friendly gui front end to select data files etc., and the convenient text file manipulating and processing of several bash scripts.

Everything works (I can press my buttons and run the shell scripts) except I can't figure out how to make things semi-portable. I would like to have a single app or package that I could distribute to others, with the needed script files somehow incorporated or generated by the app, rather than exposed to the users.

I am a noob to Xcode and AppleScriptObjC (ASOC) and I can't see the way to do this. - I can run the scripts as set of simple do shell script commands, or through commands sent to a terminal window, but that means all the individual shell files have to be distributed and put it the right place as a bunch of pieces. - I have tried to generate the script files from within the ASOC, but I run into barriers constructing the files due to the way that ASOC handles strings and special characters. I have tried both normal strings or the quoted form of string construction. As background, Apple Technical Note TN2065 is relevant. Creating the files that way loses the special characters. This code demonstrates the issue (e.g., what I am doing wrong!):

set scriptName to "/Users/me/Desktop/myScript.sh" -- Name of file
-- Define a multi line string:
set scriptContents to "       First Line - OK  
Second Line, all good so far
$Test fails - the (dollar sign)Test vanishes
\"$Test\" also fails
Last line"
do shell script ("cd " & myFolder & "; echo \" " & scriptContents & " \" > " & scriptName)

Without a way to create the needed shell scripts from within the ASOC or access the scripts if included in the application bundle as a supporting file, I will be doing a lot of tricky porting from bash to AppleScriptObjC!

Suggestions or solutions would be gratefully accepted: 1. How can I write arbitrary multi-line files with AppleScriptObjC including control characters, etc. 2. or 3. How can I package a shell script so that ASOC can run it when needed?


Solution

  • Answering my own question, after some hours of research and experimentation (with thanks to various posts on macscripter.net and autodidaktos.com):

    1. Add the script file, e.g., yourScriptFile.sh, to the project via the menu File - Add Files to (yourProject)...

    2. Include the script file in the app bundle so that it will be included with the app when distributed:

      • In the Project Navigator or the Jump Bar select your project
      • Select the "Build Phases" tab
      • Expand the "Copy Bundle Resources" section (this applies to Xcode 4.6.3, maybe different with other versions)
      • Add an item to the Bundle Resources by clicking the "+" button at the bottom of the list
      • Select the script file to add to the bundle, e.g., yourScriptFile.sh
    3. In your AppleScriptObjC script, add the following subroutine

      on applicationWillFinishLaunching_(aNotification)
          set pathToResources to (current application's class "NSBundle"'s mainBundle()'s resourcePath()) as string
      end applicationWillFinishLaunching_
      
    4. Also in your AppleScriptObjC script, add the following where appropriate:

      property pathToResources : "NSString"  -- works if added before script command
      
    5. Where appropriate, also add the following in your AppleScriptObjC script:

      set yourScript to pathToResources & "/yourScriptFile.sh" 
      -- gives the complete unix path
      -- if needed, you can convert this to the Apple style path:
      set yourScriptPath to (((yourScript as text) as POSIX file) as alias)`
      
    6. As an aside, you could then open the file for read using

      tell application "Finder"
          open yourScriptPath
      end tell
      

    It should then be possible to execute the script or copy it to somewhere for user access using the do shell script construction. It should also be possible to execute the script directly from the bundle if appropriate.