Index

Bourne Shell

Basic script necessities

fail on errors
set -e
ignore errors (default)
set +e
perform syntax check on file
sh -n [file]
check syntax of file before running
set -e
sh -n [file]
pass all command line arguments to another script
java com.myserver.Program "$@"
utility method for exiting scripts
die() {
    echo >&2 "$@"
    exit 1
}
Check for root privileges
if [ "$(id -u)" != "0" ]; then
    die "This script must be run as root"
fi
script input validation => exactly 2 arguments
[ "$#" -eq 2 ] || die "2 arguments required: [ARG1] [ARG2]"
script input validation => at least 3 arguments
[ "$#" -ge 3 ] || die "3 arguments required: [ARG1] [ARG2] [ARG3]"
fill a variable from the system input
read year
echo "$year is a leap year."
verify file is not empty
if [ -s "$_file" ]
then
    echo "$_file has some data."
else
    echo "$_file is empty."
fi
verify file size is at least
file=$1
minimumsize=$2
actualsize=$(wc -c <"$file")
if [ $actualsize -ge $minimumsize ]; then
    echo size is over $minimumsize bytes
else
    echo size is under $minimumsize bytes
fi
verify zip file integrity
unzip -t $ARTIFACT_NAME || die "invalid zip file!"
verify port is available
set +e
nc -z -w1 localhost 8080
if [ "$?" -eq 0 ]; then
    echo "port 8080 is not available!"
else
    # $? will be 1
    echo "port 8080 is in use!"
fi
depending on command line argument do:
case "$1" in
        a)
                echo "argument a"
                ;;
        b)
                echo "argument b"
                ;;

        *)
                echo "other"
esac

Variables

assign variable
KEY="value"
assign exit code of last command
CODE=$?
store result of method call in variable
LS=$(ls -l)
PLUS="before $(echo between) after"
increment variable
count=`expr $count + 1`
count=$(expr $count + 1)
count=$(echo "$count + 1" | bc)
variable with date
LOGFILE=/var/log/installer_$(date +%y-%m-%d_%T).log
Passing a named variable to another script
NAME=VALUE
. /path/to/other/script.sh
note: '.' means source, then a space, then the path to the script, $NAME will be availableevalating a string in a variable as code
variable='echo "bla" > /tmp/bla'
eval "$variable"

Environment Variables

dump environment variables
printenv
print specific environment variable
printenv HOSTNAME
set a variable
variable=value
export variable as environment variable
export $variable
set and export environment variable
export variable=value
unset a variable
unset [variable]

Config file

contents of a config file
config_dir=/path/to/dir
config_file="$config_dir/path/to/file"
load a file with config settings (dot space config file)
. settings.cfg
after reading the config file, the variables are available in the script

Processes

pid of previously executed process
$!
own PID (from within the script itself to grab its own PID)
$$
wait until all background jobs are finished
wait
wait until most recent background job is finished
wait $!
wait until proces with a specific id is finished
wait [pid]
run jobs in parallel
cat args.txt | xargs -P [threads] -n 1 echo
cat args.txt | parallel -j [threads] echo {}

functions

define function
example() {
	echo "hello world!"
}
pass param to function
example () {
   echo "Parameter #1 is $1"
}
example foo
if calling another function for a decision
function f1() {
  return 0 # = success, in other words yes for if/else
}
if f1; then

Control Flow

if else

if [ conditional expression ]
then
    statement
    statement
elif [ conditional expression ]
then
    statement
    statement
else
    statement
    statement
fi
if else with return value of another function
if tomcat_running; then
	die "port $port already taken"
call another function inside an if statement
if [ $(echo 'match') = "match" ]; then
	echo "this works!"
fi
execute function body only once
UP_TO_DATE=false

update_once() {
    if [ $UP_TO_DATE -eq false ]; then
        echo "just once"
        UP_TO_DATE=true
    fi
}
execute then if command has output
if (echo "hello" )
execute then else otherwise
if (echo "hello" | grep appel )

for each

for each (space separated argument) with raw input strings
for i in 1 2 3 4 5; do echo "repeat $i"; done
for each loop (line separated)
while read i; do echo "$i"; done < [file]
[command] | while read -r line; do echo "$line"; done
for each loop (line separated) separating result in variables
pgrep -af java | while read -r pid cmd; do echo "$pid => $cmd"; done
for each whitespace separated entry resulting from another shell command
for line in `cat lines`; do echo $line; done
for line in $(cat lines); do echo $line; done
for each with pipe
for line in $(cat lines); do echo $line | grep js; done
for each loop with wildcard
for file in *.jpg;
do
    echo "$file"
done
for each with multiple statements
for line in $(cat lines); do echo "$line"; touch "$line"; done
the same as before with pretty formatting (in console or script)
for line in $(cat lines); do 
     echo "$line"
     touch "$line"
done
executing statements conditionally based on the output of a command
for file in $(ls)
do
  grep -q "a" $file && grep -q "b" $file && echo $file
done
echo all command line arguments to a script from within the script
for a in @#; do echo "arg $a"; done
echo all command line arguments, skip the first (shift drops first argument)
shift
for a in @#; do echo "arg $a"; done
echo all command line arguments, skip the first [n]
shift [n]
for a in @#; do echo "arg $a"; done

Flags

not
if [ ! -f /tmp/check ]; then
and
if [ "$1" != "v" -a "$test" = "false" ]; then
or
if [ "$1" != "v" -o "$test" = "false" ]; then
check if is a directory
if [ -d /links ]; then
    echo "directory /links exists"
fi
check if a directory does not exist
if [ ! -d /links ]; then
    echo "directory does not exist"
fi
fail if it does not (function die defined above)
[ -d "$SOURCE_ROOT" ] || die "$SOURCE_ROOT is not a directory"
check if is ordinary file
if [ -f /tmp/file ]; then
    echo "is a regular file"
fi
check if $VARIABLE refers to a soft link
if [ -L "$VALUE" ]
check if $VALUE exists on the filesystem (can be a file, directory, link, etc.)
if [ -e "$VALUE" ]
check for output
if [ "$(ls -lA)" != "" ]; then
  echo "process has output"
if [ ! -z "$(ls -lA)" ]; then
  echo "process has output"
require string is empty
if [ -z "$foo" ]; then
        echo empty
fi
require value (not empty)
if [ "$pid" ]; then
	echo pid has a value
fi
checking the contents of a string
if [ "$test" = "false" ]; then
       echo "tests off"
fi
checking a string against a regular expression
if  echo "$test" | grep -q [regex]; then
	echo regex match
fi

documentation links

specfication
http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
flags
https://wiki.bash-hackers.org/commands/classictest
http://cis.stvincent.edu/html/tutorials/unix/bshellref
http://tldp.org/LDP/abs/html/comparison-ops.html
https://en.wikibooks.org/wiki/Bourne_Shell_Scripting/Control_flow
return values from functions
https://www.linuxjournal.com/content/return-values-bash-functions
tutorials
https://en.wikibooks.org/wiki/Bourne_Shell_Scripting
http://steve-parker.org/sh/sh.shtmL
http://www.grymoire.com/Unix/Sh.html#uh-31