4 Nashorn and Shell Scripting

This section describes the extensions of the Nashorn engine that enable you to use UNIX shell scripting features for JavaScript scripts.

You can enable shell scripting extensions in Nashorn using the jjs command with the -scripting option. For example, the following command invokes Nashorn in interactive mode with shell scripting extensions enabled:

jjs -scripting

In addition to the standard JavaScript comments (// and /* */), Nashorn supports shell-style comments using the number sign (#). If the number sign is the first character in a script, then the Nashorn shell scripting extensions are automatically enabled when you interpret the script, even if you use the jjs tool without the -scripting option. This is useful when specifying the shebang (#!) at the beginning of a script to run it as a shell executable. See Shebang.


You can use the shebang (#!) at the beginning of a script file to enable the script file to run as a shell executable. If you specify the path to the jjs tool in the shebang, then when you execute the script, the shell runs the jjs tool instead, and passes the script file to it.

The jjs tool is located in the JAVA_HOME/bin directory, where JAVA_HOME is the installation directory of the JDK (or the JRE). When you install the JDK, the JAVA_HOME environment variable is usually set up automatically. If it was not set up automatically, or if you have several versions of the JDK installed, set the JAVA_HOME environment variable to the correct path of the JDK installation directory manually.

You can specify the direct path to the jjs tool in the shebang, but it is a good practice to create a symbolic link in the /usr/bin directory as follows:

>> cd /usr/bin
>> ln -s $JAVA_HOME/bin/jjs jjs


You might have to run the ln command with root privileges using sudo.

After you set up the symbolic link, you can create Nashorn scripts that can be run as executables. Also, it is possible to add command-line options directly to the shebang statement. The following example, scriptArgs.js, shows an executable script that prints the version of the Nashorn engine and then the arguments passed to the script.

#!/usr/bin/jjs -fv
print("Arguments: " + arguments);

If you run the scriptArgs.js file as a shell executable, it is interpreted by the Nashorn engine as follows:

>> ./scriptArgs.js -- arg1 arg2 arg3
nashorn full version 1.8.0
Arguments: arg1,arg2,arg3

Alternatively, if the path to the jjs tool is in the PATH environment variable, you can point the shebang to jjs as follows:

#!/usr/bin/env jjs

String Interpolation

String interpolation is used in UNIX shells to construct strings that contain values of variables or expressions. With shell scripting features enabled, Nashorn enables you to embed variables and expressions into string literals in the same way.

For example, you can assign the result of the Date() constructor to the date variable, and then pass this variable to the string using the dollar sign ($) and braces ({}) as follows:

jjs> var date = Date()
jjs> "Date and time: ${date}"
Date and time: Mon Aug 19 2013 19:43:08 GMT+0400 (MSK)

The preceding example displays the date and time when the date variable was assigned the value returned by the Date() constructor. If you want to display the current date and time when the expression is evaluated, you can pass the Date() constructor directly as follows:

jjs> "Current date and time: ${Date()}"
Current date and time: Mon Aug 19 2013 19:49:53 GMT+0400 (MSK)

String interpolation works only for strings within double quotation marks. Strings within single quotation marks are not interpolated:

jjs> 'The variable is ${date}'
The variable is ${date}

Here Document

A here document (heredoc) specifies strings in UNIX shells that preserve line breaks and indentations. With shell scripting features enabled, you can use Nashorn to evaluate scripts with heredocs.

The following example, scriptHereArgs.js, shows an executable script that prints the first passed-in argument on the first line, then the second argument indented on the second line, and the third argument on the forth line (after one blank line).

${arguments[0]} is normal
    ${arguments[1]} is indented

${arguments[2]} is separated by a blank line

If you run the scriptHereArgs.js file as a shell executable, it is interpreted by the Nashorn engine as follows:

>> ./scriptHereArgs.js -- Line1 Line2 Line3
Line1 is normal
    Line2 is indented

Line3 is separated by a blank line

Global Objects

With shell scripting features enabled, Nashorn defines several global objects.


This global object can be used to access the arguments passed to the script, similar to how the arguments object is used, for example:

>> jjs -scripting -- arg1 arg2 arg3
jjs> $ARG
jjs> $ARG[1]

This global object maps all the current environment variables, for example:

jjs> $ENV.USER
jjs> $ENV.PWD

This global function launches processes to run commands, for example:

jjs> $EXEC("ls -l")
total 0
drwxr-xr-x+ 1 johndoe staff 4096 Aug 18 11:03 dir
-rwxrw-r--  1 johndoe staff  168 Aug 19 17:44 file.txt


The $EXEC() function can also take a second argument, which is a string to be used as standard input (stdin) for the process:

jjs> $EXEC("cat", "Send this to stdout")
Send this to stdout


If the command does not require any input, you can launch a process using the backtick string notation. For example, instead of $EXEC("ls -l"), you can use `ls -l`.


This object exposes command line options passed to nashorn "command line". For example:

jjs> print("-scripting=" + $OPTIONS_scripting);
jjs> print("--compile-only=" + $OPTIONS_compile_only);
jjs> print("-timezone="+ $OPTIONS_timezone.ID);

This global object is used to store the latest standard output (stdout) of the process. For example, the result of $EXEC() is saved to $OUT.


This global object is used to store the latest standard error (stderr) of the process.


This global object is used to store the exit code of the process. If the exit code is not zero, then the process failed.

Additional Nashorn Built-in Functions

Nashorn defines several built-in functions: echo, readLine and readFully functions are defined only for -scripting mode. Other extensions like quit, exit, load, loadWithNewGlobal, Object.bindProperties are always available.


These functions are synonymous, causing the current script process to exit to the system. You can pass an integer value as the argument that represents the exit code to be returned to the system. By default, without an argument, the exit code is set to 0, meaning that the process terminated correctly.


These functions are synonymous, causing the values passed in as arguments to be converted to strings, printed to stdout separated by spaces, and followed by a new line. The implementation involves calls to java.lang.System.out.print(string) followed by java.lang.System.out.println().

>> jjs -scripting -- arg1
jjs> var a = "Hello"
jjs> print(123, $ARG[0], a, "World")
123 arg1 Hello World

This function reads one line of input from stdin and sends it to stdout, or you can assign the result to a variable. You can also pass a string to the readLine() function to get a prompt line as in the following example:

jjs> var name = readLine("What is your name? ")
What is your name? Bob
jjs> print("Hello, ${name}!")
Hello, Bob!

This function reads the entire contents of a file passed in as a string argument and sends it to stdout, or you can assign the result to a variable.

jjs> readFully("text.txt")
This is the contents of the text.txt file located in the current working directory.


The readFully() function reads data with the method byte[] Files.readAllBytes(Path), then performs byte order mark (BOM) detection on the returned byte array to determine whether the data read is Unicode-encoded.


This function loads and evaluates a script from a path, URL, or script object.

jjs> load("/foo/bar/script.js")
jjs> load("http://example.com/script.js")
jjs> load({name:"script.js", script:"var x = 1 + 1; x;"})

This function is similar to the load() function, but the script is evaluated with a new global object. This is the primary method for creating a fresh context for evaluating scripts. Additional arguments (after the script) passed to loadWithNewGlobal() are stored in the arguments global variable of the new context.

Object.bindProperties(target, source)

This function is used to bind the source object's properties to the object target. The function enables sharing of global properties. For example, in a Document Object Model (DOM) simulation, you can share properties between the global object and the document. In a multithreading application, you can share functions across global objects of threads.

The following example shows how you can bind the obj object's properties to the global object:

jjs> var obj = {x:34,y:100}
jjs> obj.x
jjs> obj.y
jjs> x
<shell>:1 ReferenceError: "x" is not defined
jjs> Object.bindProperties(this,obj)
[object global]
jjs> x
jjs> y = Math.PI
jjs> obj.y

Note that the function Object.bindProperties(target, source) only binds properties of source that do not exist in target. In the following example, the function bindProperties tries to bind the properties of the obj object to the global object. However, the x property already exists in the global object. Therefore, the function bindProperties does not bind obj.x to global x. Thus, changing the value of obj.x does not change the value of global x.

jjs> x = 2
jjs> var obj = {x:3}
jjs> Object.bindProperties(this,obj)
[object global]
jjs> x
jjs> x = 4
jjs> obj.x
jjs> x