This program can be interesting for you if you want to write shell scripts on Unix-like platforms – but in JavaScript instead of “sh” (bourne/bash/csh and the like). All you need to know are the JavaScript basics and the usual suspects among the console commands that you often use in the shell window (e.g. “cd”, “mv”, “cp”). To see the differences and similarities, risk a glance at these shell script codes:
Bash
#!/bin/sh cd ~/Desktop echo Hello world pwd ls *.txt source otherscript.sh c=1 while [ $c -le 5 ]; do echo "Welcome $c times" (( c++ )) done if [ -f $1 ]; then echo "$1 is a file" else echo "$1 is no file" 1>&2 exit 1 fi
JavaScript
#!/usr/bin/sees
cd("~/Desktop");
alert("Hello world");
alert(pwd());
alert(ls("*.txt"));
include("otherscript.js");
var c=1;
while(c <= 5) {
alert("Welcome " + c + " times");
c++;
}
if(isfile(args[1])) {
alert(args[1] + " is a file");
} else {
throw args[1] + " is no file";
// exit(1) is not required
}
As you can see, the basic approach of SEES is implementing JavaScript code similar to the normal shell scripting. The functions you often need are in the global scope and not hidden in objects and sub-objects. JavaScript has also advantages if you write mode complex code – however, for small and mainly sequential scripts (like one if, three cp and one cd), the bash is still the tool you want to use.
Download and use
A binary is available for MacOS 10.6, you can download it here. There is explicitly no MacOS installer for it, as I don”t see a point to copy one single file to a binary directory if you possibly even don”t want this. This is a freeware program and comes without any warranties.
Run without installation
To run a JavaScript like a shell script with SEES from a folder you want, just do the following steps. These are actually almost the same steps when you create a bash script:
- Copy sees to this folder
- Create a JavaScript file in the folder (e.g. script.js)
- Make the JavaScript file executable using
chmod 711 script.js - Put
#!/.seesin the first line of the script - Thats it, you can implement your code, e.g.
echo("Hello world!"); - Run your script by typing
./script.jsin the shell window
Install SEES
Simply copy the sees binary file to the /usr/bin directory and give it the right access permissions:
- Copy:
sudo cp sees /usr/bin - Owner:
sudo chown root:wheel /usr/bin/sees - Permissions:
sudo chmod 711 /usr/bin/sees
Some Annotations
- The “.js” file extension is not required for the interpreter. If your script shall look like a command, just name it with out an extension – like
dosomething - You can make an additional private binary path where you put your scripts in:
- Create a new folder somewhere in your home directory, example:
mkdir ~/.bin(this .bin folder will not be displayed in the Finder) - Open the file
~/.bash_profileand add the lineexport PATH=$PATH:~/.bin. If it is not yet in your home folder, create it - If your terminal program is open, quit the process (in the Dock, not only the windows) and reopen it to make the changes being reloaded
- Put your script files into your
~/.binfolder - Now you can call your programs from everywhere you like
- Create a new folder somewhere in your home directory, example:
Source code version
You can compile the sees-source for other Unix-like platforms using the GCC (I used GCC4.2.1). The zip contains a NetBeans project that should compile without changes (I have to admit that I still didn”t get it managed to create an autoconf project out of it, so if you have time and the proper toolbox installed on your machine – I would be glad :-) ).
More about it …
The shell interpreter is based on the Simple ECMAScript Engine (SEE), which is written by David Leonard and published under GPL compatible BSD license. SEE is a very slim and well functioning open-source JavaScript interpreter, which can be integrated in c/c++ projects. So SEES is “SEE for the Shell”, uses the SEE library, sticks to the same license, and hence is an open-source project.
Synopsis
sees [-options] <script file> [<script arg1> [<script arg1> [...]]]
Libraries
You can write your own JavaScript libraries. The program will execute the following script files in the given order, if they exist:
- /etc/sees/library.js
- /Library/Application Support/sees/library.js
- ~/.sees_library.js
- ~/Library/Application Support/sees/library.js
All functions and variables you define in your library are available in all your scripts, as long you do not call sees with the switch "--no-library", e.g. #!/usr/bin/sees --no-library. Note that you can overload variables and functions. If the function foo() {} is implemented in /etc/sees/library.js and in ~/.sees_library.js, then the foo() will do what ~/.sees_library.js says.
Short how-to
The most comments are posted in the blog category SEES, but here some basics in place.
Reading text from a file
Here we use the function that we know from the shell: cat:
alert("The text in the file is=" + cat("textfile.txt") );
Writing text in a file
As echo text > file is used in bash, the alert/print/echo functions have two optional parameters:
alert("My text", "~/textfile.txt"); // Replace the file if it exists
alert("My text", "~/textfile.txt", true); // Append text to the file if it exists
Command line arguments
Arguments are stored in the args[] array. Like using the bash, the first parameter args[0] is the program name/path. To test this script, call it with the command line somehow like ./script argument1 "argument 2" and other arguments.
alert("I am the script " + args[0] + ", and these are my arguments:");
for(var i=1; i < args.length; i++) {
alert(" args[" + i + "] = " + args[i]);
}
Input from pipes
You can input text from pipes, like cat file.txt | myscript.js. If you do so, then the content of the text file, which was passed to your script, will be stored in the variable stdin.
alert("I've got something from a pipe here:" + stdin);
Troubleshooting
- Interpreter throws a parse error: Make sure that your script is saved in UTF8, because you have probably some special characters in it like the German “ä”, the French “é”, the Spanish “ñ” or wherever you implement :-)
Reference of build-in objects, functions and variables
What you see below is a copy of the language extensions you get when you type sees --help. All the functions are explained with argument types, and the obligatory brackets [ ] for optional parameters.
Global variables
var String stdin Contains the standard input passed to the script, e.g. by piping like cat file.txt | script.js var Array args Contains the command line arguments passed to the script, e.g. script.js -switch1 "Text argument 2" argument3 The first argument is always the script name (or what command you typed, e.g. "./script.js" or "~/scripts/script.js"
Core extension functions and objects
function sh(String <command>)
Executes a shell command, writes stdout and stderr to the console and
returns the exit code.
function exec(String <command>, [Double <timeout in s>, String <stdin text>])
Executes a program and returns the exit code, the standard output and the
error output of the program as object. You can set a program timeout in
seconds and pass a text to the stdin pipe of the program.
Other than using function sh(), this function cannot evaluate shell
redirections like "echo Any test > file.txt" or "cat file.txt 2>1".
Instead, the results are saved in the object:
Object {
String stdout
String stderr
Integer exitcode
}
function print(String <text>, [String <file path>, Boolean <append=false>])
Prints the texts to the console standard output. If <file path> is
specified, the output is redirected to a file. Optionally the output
is appended at the end of the file
Returns nothing
function println(String <text>, [String <file path>, Boolean <append=false>])
Prints the texts to the console standard output and adds a new line
If <file path> is specified, the output is redirected to a file. Optionally
the output is appended at the end of the file
Returns nothing
function alert(String <text>, [String <file path>, Boolean <append=false>])
Prints the texts to the console standard output and adds a new line
(JavaScript known alias of println). If <file path> is specified, the
output is redirected to a file. Optionally the output is appended at the
end of the file.
Returns nothing
function include(String <path to JavaScript file>)
Executes a JavaScript. All variables and functions exists after the
include has finished (which allows you to write libraries. As the
import keyword is reserved and may be used later for explicit library
loading, we use include to load any file we want in the file system.)
Returns nothing
function exit(Integer <return code> )
Returns to the parent process with a spacified exit code
function env(String <variable>, [String <new value>])
Gets or sets the value of an environment variable
In both cases the actual value of the variable is returned
Object sees {
The object contains interpreter specific functions and data:
function compatibility()
Returns the interpreter JavaScript compatibility integer
function version()
Returns the program version as double
function gc()
Runs the SEE garbage collector
Returns nothing
function gcdump()
Dumps the SEE garbage collector
Returns nothing
function help()
Returns a string containing this help text
}
Shell-command (bash) derived functions
function echo(String <text>, [String <file path>, Boolean <append=false>])
Prints the texts to the console standard output and adds a new line
(Bash known alias of println). If <file path> is specified, the output is
redirected to a file. Optionally the output is appended at the end of the
file.
Returns nothing
function ls(String <dir/pattern>, [Boolean <show hidden>, Boolean <recursive>])
Lists directory contents (like shell command ls) If you search for hidden
files (e.g. ls(".*")), then <show hidden> is automatically switched on.
Returns an Array with file and directory names
function cd(String <directory>)
Changes the current working directory (like shell command cd)
Returns a String which contains the new directory
function cwd()
Returns a String which contains the current working directory
(like shell command cwd)
function pwd()
Returns a String which contains the current working directory
(like shell command cwd)
function mv(String <directory/file>, String <new location>)
Moves a file or directory like the mv shell command
Returns (nothing)
function cp(String <directory/file>, String <directory/file>)
Copys a file or directory like the cp shell command
Returns (nothing)
function ln(String <file/dir path>, String <link path>, [Boolean <hardlink>])
Creates a symbolic link or hard link to a file or directory.
Note that hard links to directories are normally forbidden.
Returns (nothing)
function rm(String <file>)
Deletes a file like the rm shell command
Returns (nothing)
function rmdir(String <directory>)
Deletes an empty directory like the rmdir shell command
Returns (nothing)
function unlink(String <file>)
Deletes a file or directory like the rm shell command
The function is an alias for rm()
Returns (nothing)
function mkdir(String <directory>)
Creates a directory with the permissoin 755
Returns (nothing)
function chmod(String <file/directory>, [Integer <permissions>])
Gets or sets the value of file permissions
The permissions can be set as string or integer, e.g. "777" or 711
In both cases the actual permission of the file is returned
function chown(String <file/directory>, [String <owner>])
Gets or sets the file owner
In both cases the actual owner of the file is returned
function chgrp(String <file/directory>, [String <group>])
Gets or sets the file group
In both cases the actual group of the file is returned
function touch(String <file/directory>, [<modification time>, <access time>])
Sets new modification and access time of a file. If <modification time>
of <access time> is not specified, the time is unchanged. If the file does
not exist, an empty regular file is created. The data types of the times
can be a UNIX timestamp, a Date object, or a string string (see date formats
section
function cat(String <file/directory>)
Returns the content of a file
function md5(String <file>)
Returns a String which contains the md5 checksum of a given path
function kill(Integer <PID>, [Boolean <immediately=false>])
Stops a running process by sending the signal SIGTERM. If the
argument <immediately> is true, the signal SIGKILL is sent, which is
not blockable. Use this parameter only if a process does not respond.
function basename(String <directory/file>)
Returns a String which contains the basename of a given path
function dirname(String <directory/file>)
Returns a String which contains the directory of a given path
Shell related functions which have not the same name as bash commands
function exist(String <path>, [boolean <dont't follow symlinks=false>]) Returns true if the <path> exists, else false The function follows symlinks if second argument is not true. function isfile(String <path>) Returns true if <path> is a file, else false The function always follows symlinks function isdir(String <path>) Returns true if <path> is a directory, else false The function always follows symlinks function islink(String <path>) Returns true if <path> is a symbolic link, else false The function never follows symlinks function filesize(String <path>) Returns the file size of <path> in bytes function filectime(String <path>, [Boolean <dont' follow symlinks>]) Returns the file creation time of <path> as Date object function filemtime(String <path>, [Boolean <dont' follow symlinks>]) Returns the file modification time of <path> as Date object function fileatime(String <path>, [Boolean <dont' follow symlinks>]) Returns the file access time of <path> as Date object function tmpfile() Returns the path to a usable temporary file in the /tmp directory function sha1(String <file>) Returns a String which contains the sha1 checksum of a given path The function is similar to 'shasum -a 1 <path>' function sha256(String <file>) Returns a String which contains the sha256 checksum of a given path The function is similar to 'shasum -a 256 <path>' function sha384(String <file>) Returns a String which contains the sha384 checksum of a given path The function is similar to 'shasum -a 384 <path>' function sha512(String <file>) Returns a String which contains the sha512 checksum of a given path The function is similar to 'shasum -a 512 <path>'
Object extensions
String.prototype.trim() Returns a String with spaces, tabs and newline characters chopped at the beginning and end of the text. String.prototype.ltrim() Returns a String with spaces, tabs and newline characters chopped at the beginning of the text. String.prototype.rtrim() Returns a String with spaces, tabs and newline characters chopped at the end of the text.

