Command Languages

Introduction

The lecture on Operating System utilities looked at the general characteristics of utilities supplied with an O/S, and the most common of the Unix versions of these.

The most important utility is the command processor, which usually is an interpreter for a command language of some kind (procedural, graphical, etc). Command languages are distinguished by the level of object they operate on: files and processes. They also have the typical constructs of programming languages: variables, conditionals and loops.
Languages and the levels they work at
These are


Generic Command Language Operations

Contents

Manage processes
Redirect I/O
Execute commands
Variables
Loops and conditionals
Command languages and their shells have the following capabilities

Manage processes

The O/S is ultimately responsible for process management. The shell provides a simple interface to this. It allows
Process creation
In a command line environment, the shell usually provides a prompt at which you can type a command. In a GUI environment, it provides menus and supplies icons. A GUI will also usually provide a link between file types and the program that will handle them, so that selecting a file will start the corresponding program.
Process destruction
In a command line environment, a process may be killed by keyboard actions or by special programs. In a GUI environment it may be killed by window manager actions.
Running processes
Usually a process will start running immediately its program is ``selected''. There may be means of scheduling it to run at later times, to restart a stopped process, etc.
Process suspension
There will be a means of switching processor control away from a process till the user decides to resume it

Redirect I/O

Processes can read and write files. Often they read from a default ``standard input'' and write to a default ``standard output''. These are usually the keyboard and screen.

These can often be reset by the shell to read and write from different locations. They can be chained together for simple communication.

Execute commands

Most shells have a set of builtin commands. The Unix shells maintain ``current working directory'' in each shell. So the cd command must run as an internal command so that the shell can keep track of the value. The exit command, to terminate execution of the shell, must also be internal.

If a command is not an internal one, then it is expected to be run from a program on disk. The shell will have a means of searching for this (using the PATH variable in Unix and DOS). Once found, a new process will be started for this.

Variables

Command languages typically have untyped variables. They usually do not have to be declared. i.e. make it simple to use them.

Loops and conditionals

To qualify as a language, command languages must have some form of conditional and loop (or recursion or goto's). This in turn requires a Boolean mechanism. An appropriate one for process control languages is to use the termination status of a process.

A process is started and eventually terminates. It may consider that it has performed its task successfully, so its ``boolean'' value is true. If it failed, its ``boolean'' value is false. MSDOS uses errorlevel for this, Unix uses exit codes.


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 Home
Jan Newmarch (http://jan.newmarch.name) <jan@newmarch.name>

Copyright © Jan Newmarch
Last modified: Wed Mar 7 20:25:45 EST 2001