52

If I wanted to run an AppleScript from within a bash script I could call a file with the list of commands that I require to execute.

#!/bin/bash
{some commands}
osascript file.scpt
{other commands}

What, however, if I wanted to run commands that needed to be run in sequence from within bash?

An example would be

#!/bin/bash
echo
echo This will open Google Chrome in Kiosk mode
  osascript -e "tell application \"Google Chrome\""
  osascript -e "activate"
  osascript -e     "tell application \"System Events\""
  osascript -e         "key down {command}"
  osascript -e         "key down {shift}"
  osascript -e         "keystroke \"f\""
  osascript -e         "key up {shift}"
  osascript -e         "key up {command}"
  osascript -e     "end tell"
echo "Google Chrome is now open in Kiosk Mode"

I know this is a very far fetched example, but it works to explain what I am trying to do. Normally, those commands would all be written without their respective escape \ characters all over the place and less " around each command. I'd also have them inside of a .scpt file.

A solution I am aware of, is to rewrite the script using #!/usr/bin/osascript instead of bash and go from there, but I want to be able to blend. I have found that I can test for a script file, if it does exist to create one and append each command I need to that file and then execute the required script file from within bash, but that also defeats the purpose.

There is no way that mid-way through a file, I can swap the shell being used with the shebang line and then swap back after I've executed the commands necessary, is there?

Any insight would be more than welcome.

53

The argument for osascript -e can contain newlines:

osascript -e 'set x to "a"
say x'

You can also specify multiple -e arguments:

osascript -e 'set x to "a"' -e 'say x'

Or if you use a heredoc, bash interprets three characters (\, $, and `) between <<END and END but no characters between <<'END' and END.

osascript <<'END'
set x to "a"
say x
END

Edit:

Since osascript can operate with a heredoc (ie take input from /dev/stdin) then one can just write the script as a whole file and prepend with the correct shebang line:

#!/usr/bin/env osascript

set x to "a"
say x

This also allows you to save your apple script as a actual program in ~/Applications/.app using the following procedure (changing for your script's name):

mkdir -p ~/Applications/<APP_NAME>.app/Contents/MacOS
touch ~/Applications/<APP_NAME>.app/Contents/MacOS/<APP_NAME>
open -A TextEdit ~/Applications/<APP_NAME>.app/Contents/MacOS/<APP_NAME>

Ensure that both the script file in .../MacOS/ and the matches

  • Indeed you are correct. I missed the first end tell of the script. – Danijel-James W Sep 29 '13 at 1:29
  • Any reason you don't need the -e on the HEREDOC example? – iconoclast Apr 23 '18 at 14:55
  • @iconoclast Per the man page on osascript it is one line of script. -e statement Enter one line of a script. If -e is given, osascript will not look for a filename in the argument list. Multiple -e options may be given to build up a multi-line script. Because most scripts use characters that are special to many shell programs (for example, AppleScript uses single and double quote marks, ``('', ``)'', and ``*''), the statement will have to be correctly quoted and escaped to get it past the shell intact. – uchuugaka Mar 12 at 6:16
  • Sorry @uchuugaka, but I'm failing to understand how your response answers my question. In -e statement Enter one line of a script there is an -e present. But apart from that, is a HEREDOC treated as though it were a single line? – iconoclast Mar 12 at 16:24
20

You can wrap the raw AppleScript in <<EOD... The last EOD signalling the end of input has to come at the first position in the line.

(BTW, your applescript seemed to be missing an end tell after activate....)

#!/bin/bash
osascript <<EOD
  tell application "Google Chrome"
      activate
  end tell
  tell application "System Events"
      key down {command}
      key down {shift}
      keystroke "f"
      key up {shift}
      key up {command}
  end tell
EOD

echo "Google Chrome is now open in Kiosk Mode"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .