CSC128 : Introduction to UNIX

Control Structures

Command Block

Commands can be blocked together using braces ({} ).  Each command in the block must be ended with a semicolon ( ;) or a newline.  Examples:
{ ls; who; }



This will block together the commands ls and who.  Note that there must be spaces between the commands and the braces. It is customary to indent the contents of braces when used as in the second example.

Why is this useful or interesting?  By blocking these commands together, they act as a single unit for redirection (> >> and < ) and piping ( |).  
user@host:~$ ls
afile anotherfile poem verse temp.txt

user@host:~$ who
pprudhomm :0       Mar 12 14:42 (console)
shum     pts/6    Mar 12 14:20 (
yhuang2  pts/1    Mar 12 14:56 (

user@host:~$ { ls; who; } > lswho.txt

user@host:~$ cat lswho.txt
afile anotherfile poem verse temp.txt
pprudhomm :0       Mar 12 14:42 (console)
shum     pts/6    Mar 12 14:20 (
yhuang2  pts/1    Mar 12 14:56 (


Conditional Branch (if)

We can have our script test for certain conditions and run different commands based on those conditions.  The simplest form is the if construct:
if [ expression ]
   command 1
   command 2

   # Optional (may be left out if not needed).
   # Adds default code block executing if original
   # condition tests false.
   command 3
   command 4


If expression is true, then the commands listed after then are executed.  Otherwise, the commands listed after else are executed.  The if construct is ended with the fi statement. Execution then continues as normal after the fi , line by line.

Note that the
else portion can be left completely out, in which case if expression is false, the lines after the then will simply be skipped, and execution will resume after the fi


Every command returns a return value when it finishes execution. This return value is stored in the variable $? .  The expression in the if construct above is simply an executable like any other command.  If it returns zero (0), then it is considered true.  If it returns anything other than zero, it is considered false.  

A special command,
test helps us build useful expressions.  For example, the following test command lines all return true (o).
user@host:~$ test cat = cat

user@host:~$ test 5 -gt 2

user@host:~$ test astring
See man test for descriptions of all the different tests you can use.

Another name for
test is the open bracket ([ ).  The expression should end with a closed bracket (] ), and spaces should be placed between the brackets and their contents.  Examples:
user@host:~$ [ cat = cat ]

user@host:~$ [ 5 -gt 2 ]

user@host:~$ [ astring ]

while (until)

The while construct will execute and re-execute a list of commands as long as expression remains true, and then execute the commands after done as normal.
while [ expression ]
  # These commands will loop as long as
  # expression remains TRUE
  command 1
  command 2


The until construct is similar, but will continue to loop until expression becomes true, and will then continue to execute the commands after done as normal.

until [ expression ]
  # These commands will loop until
  # expression is TRUE
  command 1

  command 2



Another loop, called a for loop, makes it easy to run a set of commands on each member of a list.  
for <arg> in [ list]

This will loop once for every item in [list] , placing a different member from [list] in the variable arg each time.  An example:
user@host:~$ for i in hello my name is steve
  echo The value of '$i' is $i

The value of $i is hello
The value of $i is my
The value of $i is name
The value of $i is is
The value of $i is steve


Command Substitution

When a command is interpreted by the shell, words that begin with a dollar sign ($) are expanded, or substituted with their values.  This is called variable expansion. For example:
user@host:~$ myvar='my dog has fleas'

user@host:~$ echo $myvar
my dog has fleas

user@host:~$ echo '$myvar'

Note that when the variable is surrounded with single quotes, it is taken literally and is not expanded.  

Just as a variable has its value subsituted for it, a command can have its output substituted for it.  To do so, use the $(command) form.  
user@host:~$ ls
afile anotherfile poem verse temp.txt

user@host:~$ lsvar=ls

user@host:~$ echo $lsvar

user@host:~$ lsvar=$(ls)
echo $lsvar
afile anotherfile poem verse temp.txt

Another example, using the for loop:

# make backups of all the files in the
# current directory, by copying each of
# them to another file that ends with ".backup"

for i in $(ls)
  cp $i ${i}.backup
Note that the braces are used in cp $i ${i}.backup , to keep the variable $i lexically seperated from the text ".backup" .

(You may also use backticks (` above the TAB key) for command substitution.  The $() is generally superior:  it is easier to differentiate from single quotes, and it may be nested. )

Extended Expressions in bash

C programmers often find the Bourne shell expressions clumsy.  For these users, bash provides the extended expressions with [[ expression ]] and (( arithmetic expression ))   Examples:
[[ 5 < 2 ]]

[[ cat != dog ]]

(( (5 + 4) < 3 ))

for ((i=1; i<10; i++))
Note that these work in bash and do not work in the Bourne shell ( /bin/sh). 


sleep [seconds ]
This will suspend processing for [seconds] .  This is useful in loops within scripts, for example to make the loop cycle every 5 or 10 minutes.  

touch [filename]
This will update the time stamp on the file named [filename ] to the current time, or create a new file named [filename] with a size of zero.

lpr [filename]
This will send the contents of [filename] to the default printer.  If [filename] is not specified, then it will send stdin to the default printer.
ls -l | lpr
This will redirect the output of
ls -l to the input of lpr , which will send it to the default printer.

pr [options] [filename]
This command will format  the text file named [filename ] (or stdin if none is specified)  for output to a printer, breaking pages, etc.