Next Previous Contents

4. Using shells

4.1 Bourne-type shells

There are two main flavours of shells, the Bourne-shell (sh, ksh, bash) and the C-shell (csh, tcsh). An example of a Bourne-shell script is tofloppy:

#!/bin/sh

gzipped="false"
dev="/dev/fd0"
if [ $# -eq 1 ]; then
    case ".$1" in
    .*.gz|.*.tgz)
        gzipped=true ;;
    .*) ;;
    esac
fi

if [ ".$1" = ".-9" ]; then
        gzarg='-9'
        shift
else
        gzarg='-5'
fi

if [ "$gzipped" = "true" ]; then

echo "This will put the gzipped item $1 to the floppy disk."
echo 'Insert the floppy disk and press Return when done.'
read ans
cat $1 | dd bs=8192 of="$dev"

else

echo "This will put items $* to the floppy disk."
echo 'Insert the floppy disk and press Return when done.'
read ans
tar cfv - $* | gzip $gzarg | dd bs=8192 of="$dev"

fi

echo 'tofloppy ok. See fromfloppy [-t] for reverse operation.'

Put this in directory bin under your home directory (do mkdir bin if it does not yet exist), naming the file tofloppy, and give execution permission: chmod +x tofloppy. Then ensure that $HOME/bin is in your PATH (see PATH). After this, tofloppy is available as a command (after doing rehash if using csh or tcsh). Tofloppy is given a list of file or directory names; it makes a gzipped tarfile out of those and writes it to your floppy disk. The option -9 is recognized, it tries to compress harder. For user convenience, if only one argument is given and if it ends with .gz or .tgz, it will be written directly to disk, without tarring and compressing it first, since it is already in compressed form.

The used shell is specified in the first line reading #!/bin/sh. Since this line starts with #, the shell treats it as a comment, but the Unix kernel uses the information to execute the file using the program /bin/sh. The program name must be a full, explicit pathname here. This is sometimes a nuisance for portability, if the pathname is different on different system. One can trust that sh is always found in /bin, this is one reason why I prefer Bourne shell scripts.

A corresponding program fromfloppy looks the following:

#!/bin/sh

opts="xvfo"
showingOnly=false
if [ $# -eq 1 ]; then
    if [ "$1" = "-t" ]; then
       opts="tvf"
       showingOnly=true
    fi
fi

if [ "$showingOnly" = "true" ]; then
    echo "This will show the directory on your floppy disk."
else
    echo "This will extract the files from your floppy disk."
    echo '(Use fromfloppy -t to see the directory only.)'
fi

echo 'Insert the floppy disk, press Return when done.'
read ans
dd bs=8192 if=/dev/fd0 | gunzip | tar $opts -
echo 'fromfloppy ok. See tofloppy for reverse operation.'
fromfloppy reads a compressed tarfile stream from the floppy disk (it prompts the user to press Return first) and unpacks the files in the current directory. fromfloppy -t only shows what files are there without actually extracting them.

A summary of the shell syntax can be found in the man pages. The only problem is that the man pages are very long. Thus it is better to grab them in a text file first, by doing e.g. man sh | col -b >mansh and viewing mansh in your favourite text editor. In bash, a quick help is available by typing help.

The oldest of the shells is the original Bourne-shell, sh. It does not provide interactive sugar such as command line editing or TAB completion (command and filename completion by pressing TAB). The Korn-shell ksh is a somewhat-extended version which is the default on HP workstations, for instance. The GNU version is called Bourne-again shell (bash). It provides many nicety features while being compatible with the original Bourne-shell and is often the default shell on Linux systems. On Linux, /bin/sh is a symbolic link to /bin/bash.

4.2 C-shell

The C-shell has a different syntax for if-statements, loop statements and so on. The original C-shell does not have command line editing and is thus not suitable for interactive work. The tcsh contains these facilities. I usually use tcsh as my interactive shell but /bin/sh for my scripts.

4.3 Redirection

A summary of the input/output direction commands in different shells:

prg <input >output          # (all shells) stdin from input, stdout to output
prg 2>/dev/null | less      # (Bourne-shell) ignore error output, pipe stdout to less
prg 2>&1 >x                 # (Bourne-shell) stdout and stderr to x
prg >&x                     # (csh,tcsh) stdout and stderr to x
(prg >x) >&y                # (csh,tcsh) stdout to x, stderr to y

4.4 Job control in tcsh and bash

A program can be running in the foreground, in the background, or be in suspended state (stopped but restartable). To run the program in the background one ends the command with &. It is also possible to put a foreground job to the background by first suspending it by pressing Control-z and then typing bg. Inversely, a background job can be brought to foreground by typing fg. Thus it is not necessary to restart the program just because one wants it to run in the background. On modern systems, background jobs are usually not killed if the shell that created them exits.


Next Previous Contents