Shell Programming Using Bash

The shell has a full featured if very weird programing language.  It has variables, control structures, and input-output methods.

Why: People use bash not because it is the best progfaming language around (it's not) but because it is something of a standard.  All UNIX machines have bash.  Many important system scripts are written in bash (/etc/rc.d/* for instance).

The Start of the Program:  All shell programs should start with the line "#!/bin/bash".  This tells the kernel to hand the script to /bin/bash, and not to try and run it as if it were a binary.  Also, don't forget to set the execute bit.

Variables: You can use any reasonable variable name.  All variables are of type 'string'.  You never need delcare a variable before use.  To get the value of a variable, put a "$" in front of it.  To set a value, omit the "$".  for instance ...

a=4
echo $a

Control Structures:  Bash has all the standard control structures.  Notice that the if stuff is somewhat weird.  For instance ...

while [ $a = 4 ];
do
 echo $a
done
for a in /usr/bin/*
do
 rm $a
done
if [ $a = 4 ]; then
 echo Hi There
fi
if [ $a = 4 ]; then
 echo A is four
else
 echo A is not four
fi
if [ $a = 4]; then
 echo A is four
elsif [ $b = 4 ]; then
 echo B is four
fi

Arithmetic Expressions:  You will rarely need these, but here they are.  Do math by running the expr program.  Spaces are REQUIRED around all operands and operators of an expression.  Remember that '*' is a reserved symbol.

let a=$a+1

a=`expr 3 +$a`

Boolean Tests:  There are a million of these.  See "man test" for more details.  Here are some examples
 

Less than

$a < $b

Greater than

$a > $b

File Exists

-f $file

Dir Exists

-d $dir

 
Special Variables
There are many variables automatically set by the shell for your use.  These variables normally are read only, and tell useful things abut the state of the system.
 

PWD

The present working directory

SHLVL

Shell level -- incremented one each time -- great for recursion

UID

The User ID of the current user

LINENO

The line number currently running -- Use for debuging

PATH

The search path for commands

HOME

The home directory

CDPATH

The search path for the CD command

PS1

The primary shell prompt

PS2

The secondary shell prompt -- only used when you press return inside a quoe or block

PROMPT_COMMAND

A command that runs every time a primary prompt is displayed

noclobber

The shell will refuse to overwrite a file with ">".

$$

The current process IS of the shell -- used for temporary files

Temporary Files
It is a programing mistake to hardcode temporary filenames in a shell script.  Consider what might happen if two people run the script at the same time!  Instead, use "$$" to make each name unique.  For instance, don't use the temporary file "/tmp/backup", use /"tmp/backup.$$".

Doing math in Bash
There are lots of ways. See https://www.shell-tips.com/2010/06/14/performing-math-calculation-in-bash/. But really, when you can just use 'let'.

 
Fake Input and Fake Output
Sometimes you will want to run a program, but not want to see it's output.  Luckily, and data sent to the special device /dev/null will be ignorred.  Other times a program insists on reading data, but will happily accept all zeros.  The special file /dev/zero consists of an infinite number of zeros.  For example
    funnyprogram < /dev/zero > /dev/null

Redirecting Errors
You can redirect an error message with "2>".  This is a great way to build log files of errors. For example, to run ls but not see any error messages, try
    ls /alfj /tmp 2> /dev/null

Lists
One neat trick is to make a 'list' and then get data from the 'list'.  For example,
    (cd /home; tar cf - . ) | ( cd /newhome; tar xf - )