Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Shell Script with JavaScript for Automation

Using AppleScript I can call a shell script with:

do shell script "echo 'Foo & Bar'"

But I can't find a way to do this with JavaScript in the Yosemite Script Editor.

like image 891
sverrejoh Avatar asked Jan 20 '15 11:01

sverrejoh


2 Answers

do shell script is part of the Standard Scripting Additions, so something like this should work:

app = Application.currentApplication()
app.includeStandardAdditions = true
app.doShellScript("echo 'Foo & Bar'")
like image 164
ShooTerKo Avatar answered Sep 19 '22 13:09

ShooTerKo


To complement ShooTerKo's helpful answer:

When calling the shell, properly quoting arguments embedded in the command is important:

To that end, AppleScript provides quoted form of for safely using variable values as arguments in a shell command, without fear of having the values altered by the shell or breaking the command altogether.

Curiously, as of OSX 10.11, there appears to be no JXA equivalent of quoted form of, but, it's easy to implement one's own (credit goes to this comment on another answer and calum_b's later correction):

// This is the JS equivalent of AppleScript's `quoted form of`
function quotedForm(s) { return "'" + s.replace(/'/g, "'\\''") + "'" }

From what I can tell, this does exactly what AppleScript's quoted form of does.

It encloses the argument in single-quotes, which protects it from shell expansions; since single-quoted shell strings don't support escaping embedded single-quotes, an input string with single-quotes is broken into multiple, single-quoted substrings, with the embedded single-quotes spliced in via \', which the shell then reassembles into a single literal.

Example:

var app = Application.currentApplication(); app.includeStandardAdditions = true

function quotedForm(s) { return "'" + s.replace(/'/g, "'\\''") + "'" }

// Construct value with spaces, a single quote, and other shell metacharacters
// (those that must be quoted to be taken literally).
var arg = "I'm a value that needs quoting - |&;()<>"

// This should echo arg unmodified, thanks to quotedForm();
// It is the equivalent of AppleScript `do shell script "echo " & quoted form of arg`:
console.log(app.doShellScript("echo " + quotedForm(arg)))

Alternatively, if your JXA script happens to load a custom AppleScript library anyway, BallpointBen suggests doing the following (lightly edited):

If you have an AppleScript library you reference in JS using var lib = Library("lib"), you may wish to add

on quotedFormOf(s)
  return quoted form of s
end quotedFormOf 

to this library.
This will make the AppleScript implementation of quoted form of available everywhere, as lib.quotedFormOf(s)

like image 25
mklement0 Avatar answered Sep 23 '22 13:09

mklement0