Unix Command Language - bash

Contents

Process management
I/O redirection
Shell variables
Command substitution (grave command)
Arithmetic
Sequencing
For loop
Exit codes
While command
Conditional statement
Case statement
Quoting
Miscellaneous examples

Process management

See the lecture on Processes for information on how these can be done from C programs.

Process creation

At the command line prompt, a process may be started by typing the name of the command (and any command line arguments) and pressing return.

A set of commands may be placed in a file (using an editor). The set may be run by starting a shell with the file as argument. For example, if the file is called test_script and contains

ls
rm tmp*
then typing
bash test_script
will run the two commands sequentially. Such a file is often called a shell script or batch file.

If the shell script is made into an executable file by

chmod a+x test_script
Then typing its name at the prompt will also run the script.

If a command line finishes with an ampersand `&' then it will be run asynchronously. Without this, it will run synchronously.

The shell command interpreter reads the user input and then starts a process using the exec system call. and then

A GUI command shell will start processes by the user clicking on icons. It starts processes by using the exec or system system calls.

Command line arguments

Within a shell script

Search path

Process destruction

A process may be terminated by sending it an interrupt of some kind.

Process control

A running process may be suspended by sending it a stop interrupt and restarted by sending it a continue interrupt. From the command prompt, these operations may be done by

I/O redirection

Example

  1.     ls > tmp
        
    saves ls output in tmp
  2.     ls -l >> tmp
        
  3.     who | wc -l
        
    counts the number of people logged in
  4.     man cp | lpr
        
    sends the man page for cp to the printer
  5.     tr '\040\010' '\012\012' < file |
        sort | uniq
        
    produces an alphabetic listing of words in `file' (assuming words separated by spaces).

Shell variables

Unix shell variables consist of a sequence of letters, digits and the underscore, beginning with a letter. Variables are not declared.

From now on we only discuss the Bourne shell, Korn shell, zsh and bash. The csh and tcsh have different syntax.

Assignment to a shell variable is by

variable=value
NB: there are no spaces either side of ``=''

To use the value of a variable, prefix it with a ``$''

Example

x1=fred
x2="a string"
x3=4
x4="$x1 $x2"
echo $x1 $x2 $x3 $x4
There are some occassions when you need the value of the variable to be immediately followed by text. The variable name may be enclosed in curly brackets
x=fred
echo ${x}dy

Command substitution (grave command)

There are many occasions when you want to execute a command and keep the result around. For example, you may want to keep the list of files in the current directory stored in a variable. The grave command `...` runs the command between the accents and leaves the result in place.
file_list=`ls`
echo "The files are $file_list"
echo "The last file is"
last_file=`echo $file_list | 
  sed 's/.* //'`
echo $last_file

Arithmetic

In any of the shells, arithmetic may be done using the expr command
x=2
y=`expr $x + 2`
bash also allows you to do arithmetic using the let command
x=3
let y=$x+4

Sequencing

Commands are normally one per line. Multiple sequential commands may appear on one line separated by a semi-colon
ls; echo "files listed"

For loop

The syntax of this command is
for vbl [in values]
do
        commands...
done
NB: the words ``for'', ``do'', ``done'' must be the first words on the line. The commands can be any set of commands.

Example

for i in a b c
do
  echo $i
done

Example

cd ~/..
for i in os*
do
        echo "A student is $i"
done
A common case is to loop through all the command line arguments (positional parameters).
for i in $*
do
    echo "an arg was $i"
done
A shorthand for this is to omit the in $*:
for i
do
    echo "an arg was $i"
done

Exit codes

There are conditional expressions and while loops which use Boolean values. Commands act on files and produce visible output. Where is the Boolean value from running a command?

Every command succeeds or fails. eg. rm. may succeed at removing a file, or may fail to remove another file because of permission problems. An exit code holds this value.

The exit code is not visible. The exit code of the last command is stored in the shell variable ``?''. A value of zero stands for success, anything else for failure.

cd /tmp
echo > tmp$$
rm tmp$$
echo "Exit code of ok rm is $?"
rm tmp$$
echo "Exit code of failed rm is $?"
Generally, the exit code is not documented anywhere. The commands ``test'' and ``expr'' are the best documented, because they are often used in Boolean expressions.

While command

The syntax is
while commands
do
        commands
done
The list of commands in the Boolean part is executed each time round the loop. Usually this list is just one command, but it may be a pipeline. The exit code of the last command in this list is used as the Boolean value. If it is True (exit code zero), the commands in the body are executed.

Example

print the first 20 integers
i=1
while test $i -le 20
do
        echo $i
        let i=$i+1
done
I/O can be redirected from an entire while loop:
ls |
while read file
do
  echo "A file is $file"
done

Conditional statement

The syntax of this command is
if commands
then
        commands
fi
with variations such as
if commands
then
        commands
else
        commands
fi

Example

if a command script requires at least one parameter then this test should be used:
if [ $# -lt 2 ]
then
        echo "Usage: $0 files..."
        exit 1
fi

Case statement

The syntax is
case value in
  pattern) commands;;
  ...
  pattern) commands;;
esac
The value is some string or integer. The patterns the use shell globbing mechanism of * and ?. The matches of value to pattern take place strictly top-to-bottom, and the first match is used.

Example

Test if variable x contains a single character value, two characters, or more:

Quoting

There are some characters special to the shell, such as * and ?. The * is also special in regular expressions. If you attempt
sed s/.*//
the shell will read the * and attempt to glob it. sed will then get a list of files and complain. A quoting mechanism is used by the shell to stop it interpreting characters it shouldn't.

Interpretation of a single character is turned off by prefixing it with a backslash `\' as in

echo the amount is \$20
To echo a `\' itself, use \\.

Enclosing something in single quotes '...' turns off all interpretation, including interpretation of $, * and \.

Enclosing something in double quotes "..." allows $variable substitution but no other.

echo The cost is $20
echo The cost is \$20
echo "The cost is $20"
echo 'The cost is $20'

Single quotes in this sed command will turn off variable substitution. No quotes cause an error.

x="two words"
echo "two words are too many" |
  sed "s/$x//"

Miscellaneous examples

Example

read integers one per line from standard input until end-of-file (control-D) and print the sum
sum=0
while read x
do
    let sum=$sum+$x
done
echo "The sum was $sum"

Example

Write a shell script that takes one parameter. This parameter is a command that is to be run on all ordinary files in the current directory, and recursively in every subdirectory. (Note that the command must be in one of the absolute directories of your search path because the current directory is changed on each recursive call.)
script=$0
command=$1
for f in *
do
    if [ -d $f ]
    then
        cd $f
        $script $command
        cd ..
    else
        $command $f
    fi
done
Home Program Development using Unix Home
Jan Newmarch (http://jan.newmarch.name) <jan@newmarch.name>

Copyright © Jan Newmarch
Last modified: Wed Nov 19 17:40:25 EST 1997