-------------------------------------------------------------------       

Copyright © 2007 Richard J. Gaydos.

-------------------------------------------------------------------

CIS 3735   Chapter 10       The Bourne Shell

-------------------------------------------------------------------

2 Main Uses of a Shell

1. Command Interpreter
2. High-Level Programming Language for Shell Scripts

-------------------------------------------------------------------

Shell Script - File of Commands to be executed by the Shell

To Run a Shell Script:   filename

File MUST be EXECUTABLE to run:    chmod u+x filename

./filename    Tells the Shell to look in the WORKING Directory for 
                    the Script, rather than the normal paths for 
                    executables

The variable $PATH contains the path list

Use setenv PATH newpath   to change

Example:

echo $PATH  shows 

/usr/bin:/usr/local/bin:/usr/dt/bin:/usr/openwin/bin:/opt/SUNWspro/bin:/usr/ccs/
bin:.:/usr/ucb:/usr/local/X11/bin:/usr/local/teTeX/bin

setenv PATH ~:$PATH

echo $PATH  shows 

~:/usr/bin:/usr/local/bin:/usr/dt/bin:/usr/openwin/bin:/opt/SUNWspro/bin:/usr/cc
s/bin:.:/usr/ucb:/usr/local/X11/bin:/usr/local/teTeX/bin

making your HOME directory the first directory that is searched for a
command

-------------------------------------------------------------------

Example

man       echo "Hello there"

Remember  u+x

-------------------------------------------------------------------

Command Separators and Grouping

1.  NEWLINE  or  ;   Separate commands

         Example:    a; b; c

2. \ 	 At end of line --> Continue Command on NEXT line

         Example: cat a b \
	          c              same as  cat a b c

3. |	 Pipe

         Example:    zcat small.Z | more

4. &	 Run Command in Background

         Example:    a &        a  runs in background					

5. (    )

         Subshell

         Example:    (a ; b) & c      

                     Forks (creates) a process for  a ; b

-------------------------------------------------------------------

Job Control - Developed in  C Shell, but ...

Bourne has utility    jsh      

More on Job Control in C Shell Chapter

-------------------------------------------------------------------

Standard Error

Defaults to Terminal, like Standard Output

1> filename	Redirect Standard Output
2> filename	Redirect Standard Error

Example

Assuming  loop.cc exists in your current directory and
          loop.dd does NOT

cat loop.cc loop.dd 1> good  2> bad

then  loop.cc  will be copied to  good and
      loop.dd  error message will go to  bad 

Example

2>&1		Makes  2  a DUPLICATE of  1, so 
                       BOTH go to the SAME place

-------------------------------------------------------------------

Process - A Unit of Work that can be Identified (PID - Process ID) 
		   and Tracked (PCB - Process Control Block)

A process is USUALLY created EACH TIME you execute a command or 
  script

There is a HIERARCHICAL Structure to Processes:
Supervisor gets PID 1
Supervisor forks (creates)  getty  processes for each terminal
           so you can log in and use a shell

-------------------------------------------------------------------

Execute a Command: 	

Parent FORKS a child, then Parent SLEEPS     

unless	1. & = Background
        2. Built-ins (p. 337)

-------------------------------------------------------------------

Variables in a process are LOCAL

-------------------------------------------------------------------

Process IDs

Use   ps -l	to get info on processes, including PPID, 
                                                    Parent’s PID

-------------------------------------------------------------------

Invoking a Shell Script

1. Just enter   filename

	The Shell forks a duplicate shell (subshell)
	THIS subshell tries to execute the script as a COMMAND
	If UNSUCCESSFUL, it runs the commands IN the file

Note: You need READ and EXECUTE permission

2. Enter . filename to run the script in the SAME shell

Note: You only need READ permission on our system.
      Some systems need read AND execute permissions.

3. Enter  sh filename

	The Shell forks a duplicate shell (subshell)
	THIS subshell executes the commands IN the file

Note: You only need READ permission

-------------------------------------------------------------------

If the FIRST TWO Characters of the Shell Script are   #!
    you specify a PATH to the SHELL that should run the script

Example:    #! /usr/bin/sh    for Bourne Shell

Default on our system:

If the FIRST   Character of the Shell Script is   #   and the
         SECOND Character is NOT an !    THEN

    the  Bourne Shell will be used to run the script

-------------------------------------------------------------------

Comments in a Script

Line begins with    #   (Except the FIRST Line, see previous)

You MUST use MY comment box!!

-------------------------------------------------------------------

Shell Variables

1. Shell Variables

	A. Keyword	

              HOME: Your Home Directory
	      PATH: What Directories the Shell searches for a
				          	   command

	B. Special	

              $?  and   $#, for examples (More later)

2. User-Created Variables - Programmer creates them

-------------------------------------------------------------------

Note: Variables hold STRINGS

Note: To use variables as NUMBERS, use    expr command

Note: You can set variables in   .profile

-------------------------------------------------------------------

User-Created Variables - use Assignment Statement

Variable=expression     VERY IMPORTANT RULE: NO Spaces around  =

Examples

Person=rick		Output		Reason

echo Person		Person		No  $

echo $Person		rick		$ allows substitution

echo "$Person   xx"	rick   xx	Double Quotes ALLOW 
                                               substitution AND
                                               Preserve SPACING

echo '$Person   xx'	$Person   xx	Single Quotes SUPPRESS
                                               substitution AND 
                                               Preserve SPACING

echo ‘$Person   xx’     ‘$rick xx’      Word Smart Quotes are NOT
                                             special characters in UNIX

echo \$Person    xx	$Person xx	Backslash SUPPRESSES substitution

Example

FullName="Rick      Gaydos"

echo $FullName		Rick Gaydos
echo "$FullName"	Rick      Gaydos

Example

Files=rick*

echo "$Files"		rick*
echo $Files		rick.txt   rick.c     rickgaydos    

-------------------------------------------------------------------

Turning Off Variables

1. variable=		Sets VALUE OF Variable to NULL
2. unset variable	Variable HAS NO VALUE

-------------------------------------------------------------------

Readonly Command

Example

Person=rick
echo $Person		See   rick

readonly Person
Person=axl		See    Person: is readonly

To get a List of  readonly  variables:   Enter   readonly

-------------------------------------------------------------------

export Command - Globalizes specified variables - ONE-way 
                                                  communication

                 Similar to Call by Value in C++

Example 1 - NO use of   export

Script   testit			Script   subtest

cheese=american			echo "subtest 1: $cheese"
echo "testit 1: $cheese"	cheese=swiss
subtest				echo "subtest 2: $cheese"
echo "testit 2: $cheese"

The Output:

testit 1: american
subtest 1:
subtest 2: swiss
testit 2: american



Example 2 - USING   export

Script   testit			Script   subtest

export cheese
cheese=american			echo "subtest 1: $cheese"
echo "testit 1: $cheese"	cheese=swiss
subtest				echo "subtest 2: $cheese"
echo "testit 2: $cheese"

The Output:

testit 1: american
subtest 1: american
subtest 2: swiss
testit 2: american

-------------------------------------------------------------------

read Command - Read a line into variables, one word per variable,
                    except LAST variable gets rest of the line

Example

echo "Enter a sentence: \c"
read word1 word2 word3
echo $word1
echo $word2
echo $word3

The output, assuming you type    Here are some words

Here
are
some words

-------------------------------------------------------------------

Note:   \c   suppresses  NEWLINE

-------------------------------------------------------------------

Command Substitution - The output of the Command goes to the 
	                       Variable

variable=`command`

Example

directory=`pwd`
echo "You are using the $directory directory"

The output

You are using the /.../.../... directory

-------------------------------------------------------------------

Keyword Shell Variables

HOME	  Your working directory when you log in
			
PATH	  Specify directories in the order the Shell is to search 
	 		    them
			
	  Example
			
	  PATH=/usr/ucb:/usr/bin:/usr/sbin
	  export PATH
			
MAIL	  Name of the file that holds your mail
			
			Usually, /var/mail/loginname
			
MAILPATH  List of filenames, separated by  :, that if modified 	
	       (you receive mail), you get a prompt 
                                   (specified after a  %)
			
	  Example
			
	  MAILPATH=/var/mail/rick%Rick has New Mail
			
MAILCHECK How often (in seconds) the Shell is to Check for new 
	      mail		
	  Note: The default is 600  (10 minutes)
	  Note:  0  means  check before each prompt
			
PS1	  Holds the Shell Prompt
			
	  Example
			
	  PS1="`hostname`: "    to get    cis:   as a prompt
			
PS2	  Holds Secondary Prompt (If a  "command ... ends 
				  without  ")
			
	  Note: The default is  >
			
	  Example
			
	  PS2="More is needed: "
			
IFS	  Internal Field Separator
			
	  Note:  Blank or tab separates fields, can add more
			
	  Example
			
	  IFS=:
			
CDPATH	  If NOT set,  cd name  searches WORKING Directory for  
	                  name
	  If SET, the directories given are searched
			
          Example

	  CDPATH=:dir:dir:...

	  Note: The  colon at the beginning implies search the
	             WORKING Directory FIRST

TZ	  Time Zone, TZ=zzzHddd, where

          zzz	is Name of Time Zone
	  H	is number of hours difference from GMT
	  ddd	is Name of Local Daylight Savings Time Zone
			
	  Example
			
	  TZ=EST5EDT

-------------------------------------------------------------------

Running  .profile with the  DOT  .   command,    . .profile

The extra DOT runs the script as PART OF the CURRENT Shell

If you entered  .profile while a Shell is RUNNING, the Shell would 
   FORK, and the variables you set in the  .profile  would be in 
   effect only in THAT SUBSHELL  !  !  !

-------------------------------------------------------------------

Readonly Shell Variables

$0		The Name of the Command you used to call a program
		
$1-$9	First 9 Command line arguments
		
$*		ALL Command line arguments:   
		
$@		Like,  $*,  except quotes arguments individually 
                            IN a Double Quote String:

		       "$@"  is same as   "arg"  "arg"  "arg"
		       "$*"  is same as  "arg arg arg arg"
		
$#		Number of arguments on the command line
		
$$		PID of current process
		
$!		PID of last process you ran in the background
		
$?		Condition Code of last process

-------------------------------------------------------------------

The  shift  Command

Moves	10th		argument to	9th
		 9th		argument to	8th
				...
		 1st		argument UNAVAILABLE

Note: There is NO way to automatically UNSHIFT

-------------------------------------------------------------------

The  set  Command

set arg1 arg2 arg3 ...

Used in scripts, replaces the values of $1, $2, $3, ...   with  
     arg1, arg2, ...

-------------------------------------------------------------------

The  exit  Command

exit ConditionCode

Sets the  $?  variable  to  ConditionCode  and  exits the script

-------------------------------------------------------------------

Control-Flow Commands

-------------------------------------------------------------------

If Then Else

if test
   then
         commands
else
         commands
fi

-------------------------------------------------------------------

Example

if test $# = 0

   or

if [ $# = 0 ]

Note: Brackets MUST HAVE spaces or tabs on either side of each of them

-------------------------------------------------------------------

test Command

test expression
     or
[ expression ]
     
Also

[ exp -a exp ]		Means  AND
     or
[ exp -o exp ]		Means  OR

-------------------------------------------------------------------

test Command  string  tests

Criteria		Is TRUE if ...

string			string  is not NULL

-n string		string has a length greater than zero
-z string		string has a length of zero

string1 = string2	equal strings
string1 != string2	NOT equal strings

-------------------------------------------------------------------

test Command  integer  tests

Criteria	   Is TRUE if ...

int1 relop int2	   int1 ? int2  

from -gt >   -lt <
     -ge >=  -le <=
     -eq =   -ne not =

-------------------------------------------------------------------

test Command  file  tests

Criteria	Is TRUE if ...

-b filename	filename exists and is a block special file
-c filename	filename exists and is a character special file

-d filename	filename exists and is a directory
-f filename	filename exists and is an ordinary file

-h filename	filename exists and is a symbolic link

-g filename	filename exists and its set group id bit is set
-u filename	filename exists and its set user ID bit is set
-k filename	filename exists and its sticky bit is set

-p filename	filename exists and is a named pipe

-r filename	filename exists and you have read access to it
-w filename	filename exists and you have write access to it 
-x filename	filename exists and you have execute access to it 

-s filename	filename exists and has a size > zero bytes 

-------------------------------------------------------------------

test Command  file-descriptor  test

Criteria	     Is TRUE if ...

-t file-descriptor   the open file  file-descriptor is associated 
                         with a terminal
				
If file-descriptor  is left off, 1 (standard output) is assumed.

Note: 	0 = standard input
     	2 = standard error 

-------------------------------------------------------------------

if then elif

if test
   then
           commands
elif test
     then
           commands
elif test
     then
           commands
else
           commands
fi

-------------------------------------------------------------------

For In

for loop-index in argument-list
do
     commands
done

Example - note the absence of  $  in front of the variable  fruit

for fruit in apples oranges bananas
do
     echo $fruit
done

The output would be

apples
oranges
bananas

-------------------------------------------------------------------

for Statement

for loop-index
do
     commands
done

Example: call this script  test

for args           <---  Implies  args in  "$@"
do
   echo $args
done

If you call the script with   test a b c

The output would be

a
b
c

-------------------------------------------------------------------

while Statement

while test
do
   commands
done

-------------------------------------------------------------------

Example

Number=0
while [ $Number -lt 10 ]
do
         echo "$Number\c"  
         Number=`expr $Number + 1`
done
echo $Number

produces the output

012345678910

-------------------------------------------------------------------

until Statement

until test
do
   commands
done

-------------------------------------------------------------------

Example

secretname=rick
name=noname
echo Try to guess the secret name !
echo
until [ "$name" = "$secretname" ]
do
   echo "Your guess: \c"
   read name
done
echo Very good

could produce output like

Try to guess the secret name !

Your guess: axl
Your guess: slash
Your guess: rick
Very good

-------------------------------------------------------------------

The  break  Statement

Transfers control to the statement AFTER  done

Get OUT of the loop

-------------------------------------------------------------------

The  continue  Statement

Transfers control TO the  done  statement  

Just skip the remainder of THIS iteration, but continue the loop

-------------------------------------------------------------------

The  case  Statement

case test-string in

     pattern-1)
                 commands
     ;;

     pattern-2)
                 commands
     ;;

     pattern-3)
                 commands
     ;;

     *)
                 commands
     ;;

esac

Example

echo "Enter A, B, or C: \c"
read Letter
case $Letter in
     A)
           echo You entered A
     ;;
     
     B)
           echo You entered B
     ;;
   
     C)
           echo You entered C
     ;;
 
     *)
           echo You did not enter A, B, or C
     ;;

esac

-------------------------------------------------------------------

Patter Matches for Case are SIMILAR to an Ambiguous File Reference

Pattern		Matches

*		Any string of characters
?		Any SINGLE character
[...]		A character class   Examples  [ABC],   [0-9]
|		Alternate choices

-------------------------------------------------------------------

The  Here  Document - Input to a script WITHIN the script

command <<+
database
+     

Note: The delimiters do NOT have to be +, but they must MATCH


Example


grep -i $1 <<+
database
+

Search for  first argument  in database  (-i = IGNORE case)

-------------------------------------------------------------------

The  exec Command

1. Run command WITHOUT creating NEW process --> get PARENT’s 
       variables

exec command arguments

Similar to  .  (dot) command

2. Redirect standard input, output, error of script 
            from WITHIN the script

exec <  infile  All subsequent input comes from  infile
exec >  outfile All subsequent output goes to  outfile
exec 2> errfile All subsequent error output goes to  errfile

Note: This redirection can still be on a per-command basis:

command < file   or  command > file

-------------------------------------------------------------------

Note: /dev/tty can be used as the name of the terminal

-------------------------------------------------------------------

The  trap  Command

Traps a signal report to a process about a condition

Signal Numbers are stored in /usr/include/sys/signal.h

Signal			Number	Generating Code

Kill			  9	Kill Command with   -9  Option
				Note: Can NOT be trapped

                                kill -9 process-id   
                                     kills that process-id

Software Termination	 15	The Default of the Kill Command

Example Uses of  trap

1. trap 15		  Traps  15  and  exits the script
2. trap '' 15		  Traps  15  and  does NOTHING
3. trap 'cmd1; cmd2' 15   Traps 15  and  Executes  cmd1  and  cmd2

-------------------------------------------------------------------

Functions

Like scripts, but stored in main memory, rather than a file --> 
                                                     Quick Access

Preprocessed (Parsed) by shell --> Quick Startup

Executed in SAME shell that called the function

-------------------------------------------------------------------

Functions can be declared in

1. .profile
2. A script you want to use the function in
3. Can be entered from the command line

-------------------------------------------------------------------

Syntax

name ()
{
   
commands

}

Example

whoson()
{

date
echo users logged in
who

}

-------------------------------------------------------------------

Functions can be "Removed" by  unset

-------------------------------------------------------------------

Built-In Commands We Covered

:        continue     pwd          shift.        echo      read
test     `  `         exec         readonly      trap      break
exit     return       unset        cd            export    set

-------------------------------------------------------------------

Special Characters

newline	Start command	
;	Command separator
( )	Group commands    and   function
&	Run in background
|	Pipe
>	Redirect standard output
>>	Append standard output
<	Redirect standard input
<<	Here	document
*	Match any string
?	Match one character
[ ]	Character class
\	Quote next character
'	Quote a string, PREVENT all substitutions
"	Quote a string, ALLOW Variable AND Command substitution
`   `	Perform Command Substitution
$	Variable
.	Execute a command
#	Comment
{ }	Grouping in a function
:	NULL command

-------------------------------------------------------------------