Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

A shell/AppleScript interaction trick UNIX
In unix, most scripting languages accept line-initial # as a comment marker. This allows the file-inital shebang sequence (#!) to be used to automatically exec the interpreter on a script. I wanted this functionality for AppleScript (which I am trying to learn), but AppleScript accepts only (*...*) and -- as its comment markers, so it is basically incompatible with the shebang method.

However, there is a convention in unix that executable files that do not have a recognizable header (of which #! is one) are passed to /bin/sh for execution. This allows considerable flexibility for use with AppleScript. The most basic idea is to use a first line containing:

  exec osascript <<\EOF
and then follow it with an arbitrary AppleScript. Voila, a seemingly direct execution of an AppleScript file. Trivial example:
  exec osascript <<\EOF
  tell app "Safari"
    activate
  end tell
Now, it is difficult with osascript to pass command-line parameters to the AppleScript.

However, using this method, if the \ is omitted before the EOF, then shell variable expansion will be done on the AppleScript text before it is passed to osascript, and this is enough for most command line parameter usage. Less trivial example:
  exec osascript <<EOF
  tell app "Safari"
    activate
    if not "$1" = "" then
      if not (exists document 1) then
        make new document at the beginning of documents
      end if
      set the url of the front document to "$1"
    end if
  end tell
This yields a command you could call "safari" that will either run the browser with its default start page, or go to the page given as the first command-line arg. There are other expansions that will happen, and some of them may need to be escaped--see sh(1) for more details. Finally, if additional setup is required before the AppleScript gets run, there is no limit on the lines that can precede the "exec osascript" line. And, if you need to do cleanup afterwards, omit the "exec" and put a line containing EOF after the AppleScript, then you can do more shell lines:
  shell line
  shell line
  osascript <<EOF
  AppleScript line
  AppleScript line
  EOF
  shell line
  shell line
Well, that's the idea. I hope someone finds it helpful.
    •    
  • Currently 3.57 / 5
  You rated: 1 / 5 (7 votes cast)
 
[30,839 views]  

A shell/AppleScript interaction trick | 20 comments | Create New Account
Click here to return to the 'A shell/AppleScript interaction trick' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
A shell/AppleScript interaction trick
Authored by: macubergeek on Jun 18, '04 04:19:26PM

Excellant hint!
I'm gonna steal it immediately ;-)



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: chriscaldes on Jun 18, '04 05:03:10PM

yes - that is really cool! - I had created many elaborate scripts to get around the issue of sharing variables from shell to applescript. Now they are all useless....! Thanks for the hint!



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: bluehz on Jun 18, '04 05:30:14PM

One thing to note - I used to think the "EOF" was written in stone - but it is not - it's simply a marker. So you can just as easily use "EOF1", or "ETF", etc as long as the opening and closing markers match. This comes into play when you may want to have more than one of these setups in a single script - although it is not necessary.. it simply makes teh script a little easier to read.

Also - from what I just read - the final EOF must be in the far left column, unless you use the form of <<-EOF in which case the final EOF will ignore any whitespace before it.



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: igor on Jun 18, '04 08:42:30PM
This is old news.

Look here

[ Reply to This | # ]

A shell/AppleScript interaction trick
Authored by: gshenaut on Jun 19, '04 12:03:29AM

Dang, and I even searched for it through the archives & on google before I posted. Sorry everyone.

Greg Shenaut



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: sjk on Jun 19, '04 01:03:28AM

Well, this isn't the easiest item to choose search criteria for. :-)



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: momerath on Jun 20, '04 04:10:38PM

Don't apologize; it's handy to have macosxhints.com as a repository of authorized, working, finalized hints.



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: mstillwell on Jun 18, '04 08:52:30PM

If your script produces output, you will probably want to pipe the output to tr:

/usr/bin/osascript << END | tr "\r" "\n"

-- ...

END

Also note that compiled scripts are very much faster than osascripts. (At least in startup time.)



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: ygor on Jun 18, '04 09:41:44PM
Also note that compiled scripts are very much faster than osascripts. (At least in startup time.)
OK, now please explain to me how you get a compiled script into a shell script

[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: mrchaotica on Jun 19, '04 03:13:19AM

How do you produce output (to stdout) with an applescript?



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: Zaknafein on Jun 21, '04 02:15:32AM
Very simple:

set Value to 10
return Value


[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: gmagerr on Jun 19, '04 07:58:07AM

Hey guy's I modified a script that was posted a few weeks ago. I want to find a way to have my users machine serial number automatically entered into one of the 4 computer info fields of the sharing window. This is the best thing I've come up with. The only thing i don't like about it is that the system preferences window is visable during the whole action. I'd like to figure out how to hide that. Anyway i thought this was a cool way to use this hint. This can be used as a login script I suppose. that is if you have ARD.

[code]
exec osascript <<EOF
set Profile to do shell script "/usr/sbin/system_profiler SPHardwareDataType"
set SN_Start to ((offset of "Serial Number" in Profile) + 15)
set Partial to text SN_Start thru (length of Profile) of Profile
set SN_End to offset of " " in Partial
set SN to text 1 thru SN_End of Partial
tell application "System Preferences" to activate
tell application "System Events"
get properties
tell application process "System Preferences"
click button "Sharing" of scroll area 1 of window "System Preferences"

delay 3
keystroke tab
keystroke tab
delay 3
tell application "System Events"
repeat 5 times
keystroke (ASCII character 31)
end repeat
end tell
delay 3
click button "Access Privileges…" of tab group 1 of window "Sharing"
delay 3
set value of text field 1 of group 1 of sheet 1 of window "Sharing" to SN
click button "OK" of sheet 1 of window "Sharing"
keystroke tab -- forward tab key
tell application "System Preferences" to quit

end tell
end tell
[/code]



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: RickoKid on Jun 20, '04 05:37:56PM
Try using this to hide System Preferences:

tell application "System Preferences" to activate
tell application "System Events" to tell process "System Preferences" to keystroke "h" using command down


[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: vonleigh on Jun 20, '04 01:35:00AM

If it's going to be passed to /bin/sh anyway. Why not do it explicitly and avoid any potential trouble?

#!/bin/sh
exec osascript <<\EOF
tell app "Safari"
activate
end tell



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: gshenaut on Jun 21, '04 11:10:00AM
Here's the niftiest application of this idea I've come up with so far. This tiny little script
exec osascript <<EOF
tell app "$*"
	activate
end tell
can be used to start up any gui application from the command line. I call it "run", but another name might be preferable. It must be in your path and made executable.

For example:

run textedit
run microsoft word
run activity monitor
run quicken 2004
run poser 5.0 os x
run finale 2004b
run logic pro 6.4.2
Now, some of these could profit from additional scripting, such as causing them to open files, set templates/modes/etc, but for a quick-and-dirty CLI interface to the GUI apps, this works very well.

Note: you have to type the whole name of the app, which sometimes includes version numbers and so on.

Greg Shenaut

[ Reply to This | # ]

A shell/AppleScript interaction trick
Authored by: gshenaut on Jun 21, '04 11:17:18AM
Just a quick addendum: you can replace the "activate" with other standard applescript commands, for example "quit", and make a script of that name or some other appropriate name. Then you can say things like:
quit textedit
quit mozilla
and so on. Just a random thought. Greg Shenaut

[ Reply to This | # ]
open
Authored by: hayne on Jun 21, '04 04:05:45PM

The same functionality is available via the standard 'open' command (/usr/bin/open).
E.g.:
open -a TextEdit

Do:
man open
for more details.



[ Reply to This | # ]
open
Authored by: gshenaut on Jun 21, '04 05:55:17PM
That's similar, but not identical functionality. It needs the -a and quotes around names containing spaces, and it can't do things like "quit". Also, since it's a script, it's possible to make other customizations on "run", such as looking up the full name in a table, so you can say "run word" instead of "run microsoft word":
exec osascript <<EOF
tell app "`grep $1 < ~/etc/longnames`"
	activate
end tell

Greg Shenaut

[ Reply to This | # ]

automaitc "longnames" list
Authored by: nick on Jun 27, '05 10:19:15AM

i figured out this one:

[code]
#!/bin/sh

exec osascript <<EOF
tell app "`ls /Applications/* | grep \.app | awk -F .app '{print $1}' | sed s/'\/Applications\/'/''/ | grep -i $1 | head -1`"
activate
end tell
[/code]
so i don't have to maintain the "longnames" list.



[ Reply to This | # ]
A shell/AppleScript interaction trick
Authored by: pvdb on Apr 24, '06 09:28:48AM

Thanks, gshenaut and others, for the "exec" workaround in its many shapes and forms suggested in this thread.

I found this thread as an AppleScript newbie trying to create shebang-enabled AppleScripts, only to find out it don't work (much to my surprise, I must say!!!)

Although the "exec" workaround definitely has it uses, it's not exactly a replacement for "the real thing", though: if '#' was recognised as a token for single-line comments in AppleScript, then the above could be written as:


#!/usr/bin/osascript

tell app "Safari"
    activate
end tell

The nice thing about this script is that it would be valid AppleScript, meaning you would still be able to edit, run and debug this script in the "Script Editor", because the shebang line would be parsed as a single-line comment, but at the same time it would be an executable shell script.

You basically get the best of both worlds: it's a proper AppleScript, which you can run, compile, install etc like any old AppleScript, but at the same time it is a self-contained, executable shell script, that can be integrated with other scripts - possibly in other scripting languages like sh, perl, ruby etc - and that can also be integrated with other Unix facilities - such as cron for instance.

Compare this to the "exec" way of doing things (applies to all of the above suggested variants):


exec osascript <<\EOF
tell app "Safari"
    activate
end tell

... which is not exactly the same: this is indeed an executable shell script, but it is no longer a proper AppleScript, meaning you loose all the benefits mentioned above.

As mentioned earlier, I'm new to AppleScript, so maybe I'm missing something here, but I would have thought it to be very easy to make AppleScript treat '#' as it treats '--' ie. as a token to identify single-line comments?!?

Have the AppleScript developers at Apple dropped the ball on this one?!? I would think that as a natural consequence of creating the "/usr/bin/osascript" utility, you'd ensure proper shebang support in the interpreter?

Anyone from Apple lurking here who would be able to enter this as a feature request for the next version of AppleScript??? :-)

[ Reply to This | # ]