Operating System Automation: POSIX Shell, AppleScript, PowerShell, cmd.exe

a side-by-side reference sheet

arithmetic and logic | strings | regexes | dates and time | arrays | functions | execution control | files | directories
processes and environment | libraries | objects | reflection | contact

posix shell (1992) applescript (1993) powershell (2006) cmd.exe (1987)
version used
dash; POSIX 2008 2.1 2.0 6.1
show version
$ osascript -e \
  "AppleScript's version"
$host.version displayed at startup
$ dash foo.sh $ osascript foo.scpt PS> .\foo.ps1

DOS> powershell -file foo.ps1
when foo.bat is in the search path:
> foo
$ dash none > powershell > cmd
execute command and exit $ dash -c 'echo hi' $ osascript -e 'say "hi"' > powershell -command 'write-host "hi"' > cmd /c "echo hi"
statement separator pipelines separated by
; & && ||

lists of pipelines separated by newlines unless newline is preceded by a backslash or inside these characters:
"" '' `` ()
newline; use ⌥l (option lowercase L) to escape newline and continue statement on following line ; or newline; a newline can be escaped with a backtick: ` newlines are permitted in double quotes and after a pipe: | pipelines separated by & && ||
word separators | & ; ( ) < > space tab
block delimiters {}
do done
keyword end keyword
on funcName end funcName
{ } ( )
assignment a=1
whitespace next to = not permitted
set a to 1
copy 1 to a
$a = 1 set a=1
parallel assignment
none set {a,b} to {1,2} $a, $b = 1, 2 none
swap tmp=$a
set {a,b} to {b,a} $a, $b = $b, $a set tmp=%a%
set a=%b%
set b=%tmp%
compound assignment operators: arithmetic, string, bit none none += -= *= /= %=
+= *=
+= -= *= /= %=
<<= >>= &= |= ^=
increment and decrement none none $x = 1
variable declaration
assignment, export, readonly assignment, local, global assignment
are identifiers case sensitive? yes no no no
end-of-line comment
# comment -- comment # comment rem comment
comment out multiple lines <<EOF
another comment
(* comment
another comment *)
<# comment
another comment #>
'' null $null
null test
[ -z $v ] v = null $v -eq $null
undefined variable access '' error to access uninitialized variable $null
undefined test f [ ${foo+1} ]; then
  echo "defined"
  echo "undefined"
  set t to foo
  display dialog ("defined")
on error
  display dialog ("undefined")
end try
arithmetic and logic
posix shell applescript powershell cmd.exe
true and false
status codes:
true false

inside [ ]:
1 ''
true false $true $false
falsehoods status codes:
nonzero integers

inside [ ]:
only integers convert to booleans:
false 0
0 0.0 "" ''
logical operators
status codes:
&& || !

inside [ ]:
-a -o !
and or not -and -or -not short-circuit operators:
&& ||
inside conditional of if:
conditional expression
$(( x>0 ? x : -x )) none
are expressions statements no yes yes no
relational expression
[ $a -gt 3 ] a > 3 $a -gt 3 %a% gtr 3
comparison operators
-eq -ne -gt -lt -ge -le

= != > < none none
= /= > < >= <= -eq -ne -gt -lt -ge -le equ neq gtr lss geq leq
convert from string A="12"
$(( 7 + $A ))

`echo 73.9 + $B | bc`
set a to "12"
7 + a as integer

set b = ".037"
73.9 + b as real
7 + "12"

73.9 + ".037"
convert to string
all values are strings 7 as text & " items" [convert]::tostring(7) + " items"
arithmetic expression
$(( 1 + 3 )) 1 + 3 1 + 3 arithmetic expression must be stored in a variable:
set /a "foo=1+3"
arithmetic operators
+ - * none / % ** + - * / div mod ^ + - * / ?? % ?? + - * none / % none
integer division
$(( $a / $b )) a div b
float division
`echo " scale=5; $a / $b " | bc` a / b
arithmetic functions none e l s c none none none a none
how to use:
`echo 'e(2)' | bc -l`
arithmetic truncation
none and no floats
division by zero
integer overflow
modular arithmetic
float overflow
no floats
sqrt -2
no sqrt
random integer, uniform float echo $RANDOM 15 bit integer random number from 0 to 99
random number from 0.0 to 1.0
random 100
random 1.0
seed random numbers RANDOM=17
set r to random number with seed 17 $r = random -setseed 17
bit operators
<< >> & | ^ ~ none none none -band -bor -bxor -bnot use with set /a:
<< >> & | ^ ~
posix shell applescript powershell cmd.exe
string literal 'don'\''t say "no"'
"don't say \"no\""
$'don\'t say "no"'
"don't say \"no\"" 'don''t say "no"'
"don't say `"no`""
newline in literal yes yes yes
escapes in double quotes
\\ \"
in $' ' quotes:
\a \b \e \f \n \r \t \v \\ \' \cc \xhh \ooo
\\ \"
\n \t \r
other backslash sequences cause syntax error
`' `" ``
`0 `a `b `f `n `r `t `v
in other backtick sequences the backtick is ignored
variable interpolation count=3
"$count ${item}s"
none $count = 3
$item = "ball"
"$count $($item)s"
length s="hello"
set s to "hello"
count s
$s = "hello"
string comparison [ $USER = foo ]
[ $USER != foo ]
index of substring none set s to "foo bar"
offset of "bar" in s
returns -1 if not found:
"foo bar".indexof("bar")
extract substring s="foo bar"
set s to "foo bar"
characters 5 thru 7 of s as text
"foo bar".substring(4,3)
string concatenation c="hello, ""world" set c to "hello, " & "world" $c = "hello, " + "world"
string replication $hbar = "-" * 80
split none "foo,bar,baz" -split ","
join none @("foo","bar","baz") -join ","
sprintf `printf "tie: %s %d %f" "Spain" 13 3.7` $a = "Spain", 13, 3.7
"tie: {0} {1} {2}" -f $a
case manipulation echo "hello" | tr [a-z] [A-Z]
echo "HELLO" | tr [A-Z] [a-z]
echo -n ${A:0:1} | tr [a-z] [A-Z]; echo -n ${A:1}
strip none " hello ".trim()
pad on right, pad on left `printf "%-10s" "hello"`
`printf "%10s" "hello"`
$s = "hello"
$s + " " * (10 - $s.length)
" " * (10 - $s.length) + $s
regular expressions
posix shell applescript powershell cmd.exe
regex match s=hello
if expr $s : $rx > /dev/null
if ("hello" -match "^[a-z][a-z]*$") {
single substitution s='do re mi mi mi'
s=$(echo $s | sed s/mi/ma/)
global substitution s='do re mi mi mi'
s=$(echo $s | sed s/mi/ma/g)
$s = "do re mi mi mi"
$s = $s -replace "mi", "ma"
dates and time
posix shell applescript powershell cmd.exe
posix shell applescript powershell cmd.exe
array literal nums=(1 2 3 4) set nums to {1,2,3,4} $nums = 1,2,3,4
$nums = @(1,2,3,4)
array size ${#nums[@]} count nums
length of nums
array lookup ${nums[0]} item 1 of nums $nums[0]
array modification nums[1]=5 set item 1 of nums to 5 $nums[0] = 5
array slice ${nums[@]:1:2} items 2 thru 3 of nums $nums[1..2]
concatenation a=(1 2 3)
b=(4 5 6)
c=(${a[@]} ${b[@]})
{1,2,3} & {4,5,6} @(1,2,3) + @(4,5,6)
manipulate back of array set a to {6,7,8}
set end of a to 9
cannot remove elements from a list
manipulate front of array set a to {6,7,8}
set beginning of a to 5
cannot remove elements from a list
array iteration for i in ${nums[@]}
do echo $i
repeat with i in nums
  display dialog(i as text)
end repeat
foreach ($i in $nums) {
  write-host $i
sort none
reverse set a to {1,2,3}
set b to reverse of a
posix shell applescript powershell cmd.exe
function definition add() { echo $(( $1 + $2 )); }
function add { echo $(( $1 + $2 )); }
on add(a, b)
  return a + b
end add
to add(a, b)
  return a + b
end add
function add {
  param ($a, $b)
  $a + $b
  set /a sum=%~1+%~2
  echo %sum%
function invocation add 1 2 add(1,2) add 1 2 call:add 1 2
missing argument value '' error $null
extra arguments ignored ignored ignored
default argument value none none function add {
  param ($a=0, $b=0)
  $a + $b
named parameters none to displayNums from x to y
  set i to x
  repeat while i <= y
    display dialog (i as text)
    set i to i + 1
  end repeat
end displayNums
displayNums to 5 from 1
variable number of arguments args in $1, $2, … with number of args in $# none
return value return arg available in $? variable if a positive integer smaller than 256 argument of return or value of last statement executed
lambda declaration none none $x = { write-host "foo" }
lambda invocation none none & $x
default scope global local
nested function definition visible outside containing function disallowed
execution control
posix shell applescript powershell cmd.exe
if if [ $n -eq 0 ]
then echo "no hits"
elif [ $n -eq 1 ]
then echo "1 hit"
else echo $n " hits"
if n = 0 then
  display dialog ("0 hits")
else if n = 1 then
  display dialog ("1 hit")
  set s to n as text & " hits"
  display dialog (s)
end if
if ($n -eq 0) {
  write-host "no hits"
} elseif ($n -eq 1) {
  write-host "one hit"
} else {
  write-host "$n hits"
if %n% equ 0 (
  echo no hits
) else (
  if %n% equ 1 (
    echo one hit
  ) else (
    echo %n% hits
while i=0
while [ $i -lt 10 ]
do i=$(($i + 1))
echo $i
set i to 0
repeat while i < 10
  set i to i + 1
  display dialog (i as text)
end repeat
$i = 0
while ($i -lt 10) {
  write-host (++$i)
set i=0
  set /a i+=1
  echo %i%
if %i% lss 10 goto :loop
break/continue break continue exit none break continue
for for i in 1 2 3
do echo $i
repeat with i from 1 to 3
  display dialog (i as text)
end repeat
for ($i=1; $i -le 3; $i++) {
  write-host $i
raise exception return nonzero status error "bam!"
catch exception trap 'echo "risky failed"' ERR
  error "bam!"
on error msg
  display dialog ("error: " & msg)
end try
uncaught exception behavior stderr and continue display error and exits
posix shell applescript powershell cmd.exe
print to standard out echo "hi world" popup window:
display dialog("hi world")
write-host "hi world"
standard file handles /dev/stdin
read line `head -1 /etc/passwd` set f to POSIX file "/etc/passwd"
set a to read f as text using delimiter linefeed
item 1 of a
read file `cat /tmp/a` set f to POSIX file "/tmp/a"
set s to f as text
write to file echo "hello" > /tmp/a set f to POSIX file "/tmp/a"
open for access f with write permission
write "hello" to f
close access f
append to file echo "hello" >> /tmp/a set f to POSIX file "/tmp/a"
open for access f with write permission
write "hello" to f starting at eof
close access f
posix shell applescript powershell cmd.exe
processes and environment
posix shell applescript powershell cmd.exe
external command ls do shell script "ls" dir
backticks s=`ls` set s to do shell script "ls" $s=dir
command line args $#
must declare run handler:
on run argv
  length of argv
  item 1 of argv
  item 2 of argv
end run
speech depends on OS say "I'm a Mac" $sp = new-object -comobject "SAPI.SpVoice"
$sp.speak("I'm a PC")
environment variable shell variables are environment variables
system attribute "HOME" $env:home
command path which ping get-command ping
exit exit 0 none
set signal handller int_handler() { echo "exiting…"; exit }; trap 'int_handler' INT none
start job in background sleep 1000 & none
suspend current job ^Z none
list jobs jobs none
background suspended job bg %1 none
bring background job into foreground fg %1 none
disown job disown %1 none
posix shell applescript powershell cmd.exe
library $ cat foo.sh
function add() {
  echo $(($1 + $2));
$ cat foo.applescript
on showText(theText)
  display dialog (theText)
end showText
$ osascript -o foo.scpt foo.applescript
import library source foo.sh
add 3 7
set f to "/path/to/foo.scpt"
set foo to (load script POSIX file f)
tell foo to showText("bar")
library path none
library path environment variable none
module declaration none
module separator none
posix shell applescript powershell cmd.exe
define class on makeInt(val)
  script theInt
    property value : val
    on addOne()
      set value to value + 1
    end addOne
  end script
  return theInt
end makeInt
create object set anInt to makeInt(7)
getter and setter get value of anInt
set value of anInt to 9
invoke method tell anInt to addOne()
posix shell applescript powershell cmd.exe
class set s to "hello"
display dialog class of s
list defined variables printenv get-variable
___________________________________________ ___________________________________________ ___________________________________________ ___________________________________________


version used

The version of the language used for verifying the examples in the reference sheet.


The version number displayed at start up is the Windows kernel version. 6.1 is the Windows 7 kernel version number.

show version

How to get the version.


The customary name of the interpreter and how to invoke it.

posix shell:

On Unix, scripts are executing by passing the file containing the script to the interpreter as an argument:

$ dash ~/configure.sh

If the executable bit is set, the file can be run directly:

$ ~/configure.sh

To determine the name of the interpreter that will process the script, Unix will look for the presence of a shebang (#!) at the start of the file. If the pathname to a command follows the shebang, it will be used to interpret the script. If no shebang is present, the script will be interpreted with /bin/sh which is bash on Mac OS X and Cygwin and dash on Ubuntu.

Command line arguments which set the positional parameters $1, $2, and so on can be set upon invocation as follows:

$ dash ~/configure.sh arg1 arg2
$ ~/configure.sh arg1 arg2

Arguments can also be put on the shebang line, but this is only useful for passing options to the shell. If the file foo.sh contains

#!/bin/sh -x

then invoking it as


is equivalent to

/bin/sh -x foo.sh

Hardcoding a full path in a shebang is a common cause of portability problems because different systems may install the interpreter in different locations. The env command avoids the problem by searching the PATH directories for the command:

#!/usr/bin/env lua

powershell and cmd.exe:

On Windows, a file is a PowerShell script if it has a .ps1 suffix. There is no need to mark the script as executable. However, PowerShell is not configured to run scripts by default. To change the configuration, start a PowerShell as an Administrator and run the following command:

set-executionpolicy remotesigned

It is possible to invoke a PowerShell script by specifying the PowerShell interpreter as the command and the script as an argument, but the suffix of the file must still be ps1:

powershell -file .\test.ps1


How to invoke the REPL.


The closest to a AppleScript REPL is to launch the AppleScript Editor. Snippets of AppleScript code can be entered into the upper pane. When the Run button is clicked, the return value of the last statement executed will be displayed in the lower pane.

execute command and exit

How to pass a single command to be executed as a command line argument.

statement separator

How the parser determines the end of a statement.

posix shell:

A posix shell simple command consists of optional variable assignments, followed by a command and zero or more arguments and redirections. The command can be an external command, user defined function, or built-in.

A posix shell pipeline is a sequence of one or more simple commands joined by pipes |. The shell executes the commands in parallel and redirects the stdout of each command to the stdin of the following command. The exit status is the status of the last command.

The control operators ; & && || are pipeline separators. The semicolon ; enforces sequential execution. The ampersand & executes in parallel. The && executes to the first pipeline that returns a nonzero status. The || executes to the first pipeline that returns a zero status.

A list is one or more pipelines joined by control operators. A list can have a semicolon ; or ampersand & at the end. A list is terminated by a newline.

A newline does not terminate a list when:

  • inside single quotes '', double quotes "", backticks ``, or parens ()
  • inside a block started by the keywords: for, select, case, if, while, until

A newline that would normally terminate a statement can be escaped with a backslash.

Multiple lists can be grouped inside parens ( ) or curly brackets { }. When grouped inside parens, the lists are executed inside a subshell. The curly brackets, but not the parens, must be separated from their contents by white space. Also, within curly brackets, but not within parens, the last list must be terminated by a semicolon or newline.


word separators

block delimiters

How blocks are delimited.


Blocks can be delimited with {}, (), or the do,done keywords.

If a block is started with an open curly bracket {, then the block must be terminated with a line containing a close curly bracket by itself }.

If a block is delimited by (), then the commands in the block are executed in a subshell.

A block is delimited by do and done when using the execution control keywords for, select, while, and until.

The then and else keywords of an if statement start blocks which are terminated by a following elif, else, or fi.

The function and if keywords open blocks which are terminated by end keywords. The repeat keyword opens a block which is terminated by until.


How to assign a value to a variable.


set and copy are not synonyms when operating on lists, records, or objects. The set command makes the left variable an alias of the right variable: the two variables then refer to the same array, record, or object. The copy command will put a copy of the array, record, or object contained in the left variable.

parallel assignment

How to assign values to variables in parallel.


How to exchange the values held by two variables.

compound assignment operators: arithmetic, string, bit

The compound assigmment operators for arithmetic, string, and bit operations


Note that /= performs float division, even when both operands are integers.

When the left operand is a string, += concatenates the right operand to the left operand.

When the left operand is a string and the right operand an integer, *= concatenates the left operand with itself right operand times.

increment and decrement

The C-style increment and decrement operators which can be used in expressions.

variable declaration

How to declare a variable.


The following three lines have identical behavior:

A="hello, world"
declare A="hello, world"
typeset A="hello, world"

It is possible to make a read only variable. Again there are three ways:

readonly A="can't change"
declare -r A="can't change"
typeset -r A="can't change"

Variables are not exported to subprocesses unless declared to be exported:

export A="exported to subprocess"
declare -x A="exported to subprocess"
typeset -x A="exported to subprocess"

Variables assigned on the same line as a command are not created, only exported to the subprocess that instantiates the command:

EDITOR=emacs svn commit

By default variables defined inside functions are global. They can be declared to be local:

function foo () {
  local b=17
  # echoes 17:
  echo $b
# echoes nothing:
echo $b


Variables can be declared as local or global. It is not possible to initialize a variable in a declaration. Undeclared variables are local: in the example below, c and e are not visible outside the function foo:

on foo(a,b)
  local c
  global d
  set c to a+b
  set d to a+b
  set e to a+b
end foo

are identifiers case sensitive?


In AppleScript, identifiers are case insensitive. This holds for reserved keywords as well as user defined variable names. The AppleScript Editor converts all keywords and identifiers in the source code to lower case when it is compiled.


PowerShell identifiers are case insensitive.

to end-of-line comment

How to make the remainder of the line a comment.


The # syntax for comments is only available in non-interactive shells unless the INTERACTIVE_COMMENTS option is set. If an interactive shell encounters a # where a command is expected a command not found error will result.

multiline comment

How to comment out multiple lines.


The method described is the syntax for a here document, which is a multiline string literal.


The null literal.

null test

How to test if a value is null.

undefined variable access

The value of an undefined variable, or the system behavior if there is no such value.

undefined test

How to determine if a variable is undefined.

posix shell:

The expression ${var+val} is val if var is defined, otherwise it is the empty string ''.

The expression ${var:+val} is val if var is defined and not null, otherwise it is the empty string ''.

Arithmetic and Logic

posix shell:

The POSIX shell provides at least three different environments for logical expressions, each with their own operators and values for true and false.

Logical expressions are usually encountered in the conditionals of if, elif, while, and until. A command is expected as the conditional expression. The command is executed, and a return value of zero is treated as true and nonzero as false.

status codes [ ] $(( ))
where used command command argument
true true no canonical true value 1
false false '' 0
falsehoods nonzero exit status '' 0
logical operators && || ! -a -o ! && || !
grouping { } \( \) ( )
string comparison operators none = != \< \> none
arithmetic comparison operators none -eq -ne -lt -gt -le -ge == != < > <= >=
arithmetic operators none none + - * / % **
bit operators none none << >> & | ^ ~

posix shell: status codes:

Logical expressions can be formed using status codes returned by commands. The commands can be external, built-in, or user defined functions. A status code of zero is used to indicate success, and for the purpose of logic zero is treated as true and all other status codes as false.

The && and || operators are short circuit operators. An exclamation point ! can be used to negate the status code of a command. It is not necessary to separate && and || from their operands with whitespace, but it is necessary to mark off a ! used as negation with whitespace.

posix shell: test command:

posix shell: arithmetic expansion:

true and false

The literals for true and false.


Values which are false in conditional expressions.

logical operators

Logical and, or, and not.


&& || and ! are available inside [[ ]], (( )), and $(( )) expressions. Inside [ ] expressions use -a, -o, and !.

conditional expression

The syntax for a conditional expression.

are expressions statements

Whether an expression can be used where a statement is expected.

relational expressions


Bash has three types of relational expressions: [[ ]], [ ], and (( )). For a description of [ ], read the man page for test.

(( )) evaluates its contents in the same manner as the arithmetic expansion $(( )). If the result is zero, it returns 1 (false). Otherwise it returns 0 (true).

[[ $a == pattern ]] and [[ $a != pattern ]] interpret * and ? on the right side as patterns. Thus "hello" == "hell*" is true. For numeric comparision, use [ $a -eq num ] or [ $a -ne num ].

Bash expressions discusses the different types of bash expressions in more detail.

comparison operators


If == and =! have an unquoted string on the right, then * and ? within the string will be treated as wild cards for matching.


Many verbal synonyms for the comparison operators are provided. For = the synonyms are equals, is equal, equal to, and is equal to.

convert from string


All values are strings. The $(( )) operator will interpolate any variables and then evaluate the resulting string as an arithmetic expression composed of integers. The variables are not limited to containing integers. The following script outputs 10:

echo $(($A))

To perform floating point arithmetic, bash must shell out to a floating point utility such as bc.

convert to string

arithmetic expressions

How to evaluate an arithmetic expression.


Bash arithmetic is available within $(( )) and (( )). The latter form evaluates the arithmetic expression and returns status 1 if the result zero, and 0 otherwise.

Bash only has integer arithmetic. For floating point arithmetic, use the external commands bc or dc.

arithmetic operators

The operators for addition, subtraction, multiplication, float division, integer division, modulus, and exponentiation. Some languages provide a function pow instead of an operator for exponentiation.


arithmetic operators are available in $(( )) and (( )).

integer division

How to perform integer division.

float division

How to perform floating point division, even if the operands might be integers.


The bash shell lacks built-in floating point arithmetic. bc is an arbitrary precision calculator, and scale is the number of digits to the right of the decimal point. If scale is not specified, it defaults to zero, which results in integer division.

It is also possible to use dc, which is a reverse polish notation arbitrary precision calculator:

`echo " 5 k $a $b / p " | dc`

arithmetic functions

Functions for computing square root, natural exponent, natural logarithm, sine, cosine, tangent, arcsine, arccosine, arctangent, and atan2.

The trigonometric functions are all in radians. atan2 takes two arguments which are the x and y co-ordinates of a vector in the Cartesian plane. It returns
the angle to the positive x-axis made by the vector.


There is a zsh module which provides the standard transcendental math functions. It is not installed by default on Mac OS X, the CentOS distribution of Linux, or Cygwin. The module can be compiled into the zsh, or it can be in a shared library which is loaded with the command zmodload mathfunc.

arithmetic truncation

division by zero

integer overflow

float overflow

sqrt -2

The result of taking the square root of -2.

random integer, uniform float

The examples show how to generate a uniform random integer in the range from 0 to 99, inclusive; how to generate a uniform float in the range 0.0 to 1.0; how to generate a float from a standard normal distribution


$RANDOM evaluates to a random integer between 0 and 32767 inclusive.


$RANDOM evaluates to a random integer between 0 and 32767 inclusive.

seed random numbers


Bash 3.2.48 seeds the random number at start up using the current time and the PID:

  /* Seed the random number generator. */
  sbrand (dollar_dollar_pid + shell_start_time);

Here is the random number generation code:

/* A linear congruential random number generator based on the example
   one in the ANSI C standard.  This one isn't very good, but a more
   complicated one is overkill. */

/* Returns a pseudo-random number between 0 and 32767. */
static int
brand ()
  rseed = rseed * 1103515245 + 12345;
  return ((unsigned int)((rseed >> 16) & 32767));    /* was % 32768 */


Zsh rand and srand from the standard C library to generate random numbers. It uses the current time at startup to seed the random number generator. Here is the source code from zsh 4.3.9:

    gettimeofday(&shtimer, &dummy_tz);    /* init $SECONDS */
    srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */


The initial seed is set to a value that varies each time AppleScript is started up.

If a repeatable sequence of random numbers is desired, the seed can be set to a specific value using the with seed parameter on the first call to random.


The initial seed is set to a value that varies each time PowerShell is started up.

If a repeatable sequence of random numbers is desired, the seed can be set to a specific value using the -setseed option on the first call to random.

bit operators


The bit operators are available in $(( )) and (( )).


string literal

The syntax for a string literal and how to escape the delimiter.

newline in literal

Whether a newline character sequence can be included in a string.

For all the languages described in this reference sheet a string literal is permitted to encompass multiple lines in the source code and the resulting string will contain the same number of lines.


Character escape sequences which can be used in string literals.

variable interpolation

How to interpolate variables in a string.


A dollar sign $ can be backslash escaped to prevent variable interpolation:

echo "the value of \$a is $a"


A dollar sign $ can be backtick escaped to prevent variable interpolation:

write-host "the value of @@`@@$a is $a"


How to get the length of a string.


strLen implementation

string comparision

How to determine if two strings are equal or unequal.

index substring

How to find the index of the start of a substring in a string.

extract substring

string concatenation

The string concatenation operator.


How to split a string into an array of strings.


When splitting a string into words, no delimiter need be specified and the string to be split can follow the -split operator:

-split "foo bar baz"


How to concatenate the elements of an array into a string with a separator.



How to create a string using a printf style format.

case manipulation


pad on right, pad on left

Regular Expressions

regex match

How to test whether a regular expression matches a string.

posix shell:

The double square bracket operator [[ ]] is not part of the POSIX standard but it is a feature of bash, ksh, and zsh. It supports a match test operator:

if [[ "hello" =~ ^[a-z][a-z]*$ ]]; then

single substitution

How to replace the first occurrence of a pattern in a string.

posix shell:

The following parameter expansion is not part of the POSIX standard but provided by bash, ksh, and zsh:

str='do re mi mi mi'
echo ${str/mi/ma}

global substitution

How to replace all occurrences of a pattern in a string.

posix shell:

The following parameter expansion is not part of the POSIX standard but provided by bash, ksh, and zsh:

str='do re mi mi mi'
echo ${str//mi/ma}

Dates and Time


bash zsh applescript powershell
array list array
dictionary record

array literal

Array literal syntax.

array size

How to get the number of elements in an array.

array lookup

How to access a value in an array by index.

array slice

How to slice a subarray from an array.

array iteration


How to test for membership in an array.


How to compute an intersection.





universal predicate

How to test whether a condition holds for all members of an array. Always true for an empty array.

existential predicate

How to test whether an item in an array exists for which a condition holds. Always false for an empty array.

dictinoary literal

dictionary size

dictionary lookup

dictionary iteration

out of bounds behavior


Python has both functions and methods. Ruby only has methods: functions defined at the top level are in fact methods on a special main object. Perl subroutines can be invoked with a function syntax or a method syntax.

function definition


A bash function definition can alternately be preceded by the keyword function, and when used, the parens following the function name are prohibited.


A zsh function can be defined with the preceding keyword function, the trailing parens, or both.


Functions are called handlers in AppleScript.

function invocation


The syntax for invoking a function is the same as the syntax for invoking a command. If a function is defined with the same name as a command in the search path, the function will be executed.

missing argument value

Value of an argument variable if a function is invoked with fewer arguments than are declared.

extra arguments

If a function is invoked with more arguments than are declared, how the function can access them.

default argument value

How to declare a default value for an argument.

variable number of arguments

How to write a function which accepts a variable number of argument.

named parameters

How to write a function which uses named parameters.


Named parameters are called labeled parameters in the AppleScript documentation. The label must be one of the following prepositions:

about, above, against, apart from, around, aside from, at, below, beneath, beside, between, by, for, from,
instead of, into, on, onto, out of, over, since, thru/through, to, under

For readability the definite article the can be inserted in between the label and the argument in either the function definition or the invocation.

To use other names for parameters, the given keyword can be used in conjunction with colon syntax:

on displayNums given startAt:x, endAt:y
  set i to x
  repeat while i <= y
    display dialog (i as text)
    set i to i + 1
  end repeat
end displayNums

displayNums given startAt:1, endAt:5

When a given parameter takes a boolean value as an argument, the with or without keywords can be used when the handler is invoked. Consider the following handler definition:

on foo given flagLabel:flag
end foo

Here are two ways to invoke foo with flag set to true:

foo given flagLabel:true
foo with flagLabel

Here are two ways to invoke foo with flag set to false:

foo given flagLabel:false
foo without flagLabel

return value


Bash functions can only return small integers via return. However, a function can echo to stdout and the caller can invoke it with backticks to get a string value.

lambda declaration

How to define a lambda function.

lambda invocation

default scope


By default, bash and variables inside functions have global scope.

Execution Control


Some optional branching constructs:


case $a in (0) echo "no";; (1) echo "yes";; (2) echo "maybe";; (*) echo "error";; esac



Also has an until loop.


break exits a for or while loop immediately. continue goes to the next iteration of the loop. redo goes back to the beginning of the current iteration.



A C-style for loop:

for ((i=0; i<10; i++ )); do echo $i; done


If a block of code needs to be executed a set number of times but no index variable is needed, AppleScript provides this alternate syntax:

repeat 3 times
    display dialog ("tut")
end repeat

raise exception

How to raise an exception.


It is possible to associate an error code with the error using the number label:

error "bam!" number 7

If no error number is specified, then the value -2700 is used.

catch exception

How to handle an exception.


If a variable name is specified after on error the error message is stored in it. There can only be one error clause and it catches all errors. To perform conditional error handling, use the number label and provide a variable name after it. The error code will be stored in that variable.

  error "bam!" number 7
on error msg number errorCode
  if errorCode = 7 then
    display dialog ("error: " & msg)
    display dialog ("unknown error")
  end if
end try

A try block can be closed by end error in addition to end try.

uncaught exception behavior

System behavior if an exception goes uncaught. Most interpreters print the exception message to stderr and exit with a nonzero status.


The bash interpreter writes a message to stderr whenever a command returns a nonzero status. By default, the interpreter does not exit, but if this behavior is desired, then the following should be put at the top of the script:

trap exit ERR

wait on thread


print to standard out


To prevent echo from appending a newline to the output, use

echo -n "hello"

standard filehandles


AppleScript does not in general run with stdin and stdout filehandles. When osascript is invoked as a shebang it is possible to read from stdin and write to stdout, however:

#!/usr/bin/env osascript 
set stdin to do shell script "cat" 
"Received from stdin: " & stdin

Here is how the above script would be invoked:

$ echo "foo" | ./stdin-example.sh 
Received from stdin: foo

read line

read file

write to file

append to file


Processes and Environment

external command


The syntax for calling an external command is the same as the syntax for invoking a function. If a function is defined with the same name as an external command in the search path, the function is invoked.


command line args


How to make the computer talk.

bash, zsh:

On Mac OSX the command say can also be executed from the bash or zsh prompt:

say "I'm a Mac"

On Ubuntu Linux this command can be used:

espeak "I'm Unix"

environment variable

command path

The directory containing a command. Also indicates if the command is a built-in, alias, or function. Shows the definition of aliases and functions.


zsh has both which and which -a. The latter shows all occurrences of a command in the search path.



The exit status of a bash script is the return status of the last command executed, or the argument of exit.

set signal handler



What a library looks like.

import library

library path

module declaration

namespace separator


define class

create object


define method

invoke method


default method





POSIX 2008
dash man page
ksh man page
bash man Page

On most modern systems if you invoke /bin/sh you get the bash shell. If your script might get run by the older Bourne shell (1977), here are the differences to think about.

A function and a variable can have the same name. User defined variable identifiers cannot start with a digit. Variables are normally global, but can be made local to a function with the local keyword, which is useful for recursive functions.

The behavior of a shell script is dependent on its environment. All environment variables that existed when the shell process starts become variables in the script’s namespace. If the name of a command does not resolve to a shell built-in command or a function defined by the script, the shell searches the $PATH variable for an external command to run. The shell will expand ?, *, and ~ in words using the local file system.

The shell is good at launching external processes and redirecting their stdin and stdout to files or other processes with >, >>, , 2>>, or 2>&1.


  • AppleScript Editor, osacompile, oascript
  • getting dictionary for application, sending commands to an application
  • I/O (display dialog, say, log)
  • applications, windows, tabs
  • open scripting architecture (OSA)



cmd.exe is the command line interpreter for OS/2 as well as Windows NT, XP, Vista, and 7.

A file of commands intended to be interpreted cmd.exe is called a batch file. By default cmd.exe will echo each command in the file before executing this. To prevent one line from echoing put and ampersand @ at the start of the line. To prevent all lines in the file from echoing, put @echo off at the top of the file. Echoing can be re-enabled later in the file with the echo on command.


Origin of the term "Shell" Pouzin

Louis Pouzin wrote a program called RUNCOM for the CTSS operating system in 1964. RUNCOM could execute scripts which consisted of CTSS commands. Development of Multics began in 1964 and Pouzin wrote a paper describing how the Multics command language could be designed with scriptability in mind. In the paper he coined the term "shell" for the interpreter of such a scriptable command language. The Multics shell was implemented by Glenda Schroeder and a developer from GE. The term "shell" was applied to the Unix shell in 1971. The use of the letters rc in Unix startup files such as .bashrc and .vimrc has as its origin the abbreviation for the CTSS RUNCOM program.

The DOS prompt COMMAND.COM and its successor in Windows NT based systems CMD.EXE are the equivalents of Unix shells. In particular they are scriptable. However, Microsoft did not call them shells, at least in the early days. Microsoft used the term shell with a different meaning from the Unix community. For example in 1988 Microsoft introduced a GUI file manager called DOS Shell. It could be launched at the DOS prompt with DOSSHELL. The Windows GUI which in the case of Windows 3.1 could be launched from the DOS prompt with the command WIN was also called a shell. Neither DOSSHELL nor the Window shell are scriptable, however.

The development environment for the classic Mac OS was called the Macintosh Programmer's Workshop or MPW. It included a command line shell based on the Unix csh called MPW shell. With the switch to Mac OS X the default Mac command line shell became tcsh and subsequently bash with Mac OS 10.3.

The application HyperCard which became available on Macs in 1987 included a scripting language called HyperTalk. AppleScript appeared in 1993 and was HyperTalk extended to the entire Macintosh OS. Mac OS thus became a GUI shell, perhaps the first. Also in 1993 the first version of Microsoft Office was released in which the applications were scriptable via Visual Basic.

Unix Shell History

shell comparison chart

The Thompson shell (sh: 1971) had limited programmability. if and goto were implemented as external commands. The command line arguments were available in the variables $1, $2, and so on. The name of the script was available in $0. The Thompson shell used <, >, and | for redirection.

Here is an example of a Thompson shell script:

if -e $1 goto exists
echo "no such file"
echo "file exists"

In the Programmer's Workbench Unix (1975-1977) which Bell Labs released internally to other parts of AT&T the Thompson shell was replaced by an upgrade which was called the PWB shell or the Mashey shell. It implemented if and goto as built-ins and introduced single letter environment variables. Two environment variables were pre-defined: $s for the user's home directory and $p for the user's search path.

The Bourne shell (sh: 1978) eliminated the goto and introduced while and for loops. Since System 7 (1979) it has shipped in place of the Thompson shell.

The C Shell (csh: 1978) by Bill Joy offered execution control statements with C inspired syntax. It introduced job control and history. It also used ~ for the user's home directory and ~username for the directories of other users. The C Shell programming environment was criticized: Tom Christiansen (1996) and Bruce Barnett (2001). Here is a side-by-side comparison of some differences with the Bourne shell:

Bourne Shell C Shell
if [[ expr ]]

elif [[ expr ]]


if ( expr ) then

else if ( expr ) then


if ( expr ) stmt
while [ expr ]

while ( expr )

for name in wordlist

foreach name ( wordlist )


The Korn Shell (ksh: 1982) added job control and history, but otherwise stayed compatible with the Bourne shell.

The TC Shell (tcsh: 1983) extended the C Shell with command line completion and command line editing. The name of the shell refers to the TENEX operating system which used long names for commands and files but offered command line completion.

The Bourne Again Shell (bash: 1987) is an open source implementation of the Bourne shell, with csh and ksh features. On many modern systems sh is the Bourne Again Shell.

AppleScript History

HyperTalk was developed in 1987 for HyperCard on the Macintosh. AppleScript appeared in 1993. It was HyperTalk extended to the entire Macintosh operating system.

cmd.exe and PowerShell History

CP/M Builtin Commands

The CP/M operating system was developed in 1973 by Gary Kiddall. It was used on computers such as the MITS Altair which employed the Intel 8080 or the Zilog Z80 chip. CP/M used drive letters (A:, B:, …) and filenames limited to 8 characters with a 3 character extension. A few CP/M command names would also persist in DOS: DIR, REN, TYPE. CP/M was written in PL/M, a version of PL/I developed by Kiddall for Intel which targeted microcomputers. CP/M was developed on a PDP-10 running the TOPS-10 operating system.

Negotiations with Kiddall to provide an operating system for the IBM PC fell through, so Microsoft purchased a version of CP/M that had been ported to the Intel 8086 and adapted it to IBM's needs. The new operating system was branded as PC DOS on IBM machines and MS-DOS when running on clones. The command line interpreter was called COMMAND.COM.

Early versions of Windows ran as a DOS application and required a DOS license. Starting with Windows 95 the separate DOS license was no longer required, though DOS was still used in the boot process. Windows NT, by contrast, did not use DOS to boot.

cmd.exe was the command prompt for OS/2 (1987). It provided most of the functionality of COMMAND.COM, the command line interpreter of DOS and early versions of Windows including Windows 3.1 (1992) and Windows 95. Window NT (1993), Windows XP (2001), and later versions of Windows also use cmd.exe.

COMMAND.COM and CMD.EXE provided rudimentary programming environments compared to Unix shells. In 2006 Microsoft released the more fully featured PowerShell. It included a large number of Unix aliases. It also introduced commandlets which are commands implemented by .NET objects and run in process by the PowerShell.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License