74

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.

2 Answers 2

77

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

5
  • Indeed you are correct. I missed the first end tell of the script. Sep 29, 2013 at 1:29
  • Any reason you don't need the -e on the HEREDOC example?
    – iconoclast
    Apr 23, 2018 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, 2019 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, 2019 at 16:24
  • @iconoclast - one simple rule for this. If you can | pipe into a command, then you can HEREDOC to it, as both methods are communicating with the command via stdin. This also means you can use the command as a shebang, e.g. /usr/bin/osascript. (Which is also using stdin to send input to the process). Try echo "set Volume 2" | osascript for a quick test.
    – ocodo
    Jul 9, 2022 at 2:44
34

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 .