Shells

A shell is a program which stands between the userl and the operating system. Its main purpose is to load and run other programs when requested. There are several shells available for Unix/Linux:

The modern shells, bash and zsh, basically started with sh and then added features of both tcsh and ksh as the authors saw fit, without breaking Bourne compatibility. (Similarly, Unix began with the Bell version (SysV). Berkeley Unix (BSD) made improvements and changes, and Linus Torvalds picked and chose what he liked the best to create Linux. In turn, some Linux features have fed back into BSD to create Apple’s OS-X.)

With only one (noted) exception, everything in the rest of this presentation applies to both bash and zsh. Most of the examples work with ash, too.

BASH

At minimum, bash or another shell provides a command prompt where a user types his or her intentions in the form of command lines. For example:

> cp -a file1 file2
>

where > is the prompt, cp is the command, -a is an option, and file1 and file2 are arguments.

The“command” can be external—a seperate program file to be run, internal—built into the shell for speed, a script— a series of commands stored in a file and executed by the shell as if typed in at the terminal, or a function—a script provided by the user which the shell keeps internally for speed. Any of these can be called via an easy-to-remember alias created by the user.

When necessary, a script can indicate on its first line which shell is to be used to execute the rest, using the magic sequence #!, often called a shebang from “hash-bang”, the slang terms for the two characters. If there is no explicit shell given, sh (or whatever is aliased to sh) is assumed. Here’s a simple example of a script:

> cat bin/unzipall

#!/bin/bash
# Loop to unzip all files given on the command line

for i in $@ 
do
  unzip $i
  echo $i
done

This script could have been typed in as a single line at the command prompt, using semicolons to separate the parts:

>for i in $@; do unzip $i; echo $i; done
The main advantage of the shell script is that it can be reused at will. In order to be executable by name, you must do two things:
  1. Give it “executable” permission, typically by the command chmod 755 scriptname.
  2. Move it to a directory on your path. The most common way is to create the directory bin in your home directory, and add it to the path via something like export PATH= ~/bin:$PATH in .bashrc. Then you can move the scripts you create there. Otherwise you have to give the full name on the command line: /home/dierdorf/bin/myscript or ./myscript2. (Remember that neither your home nor your current directory is in PATH.)

When writing all but the most straightforward scripts, the two most important features of the shell’s language are loops, shown above, and tests, used to select alternatives. Here’s an example of a script with a test:

>cat bin/wdiff

#!/bin/bash
cd ~/words
if [[ -d /dell/words/ ]] 
  then diff -q --to-file=/dell/words/ ww.html nono.html 
  else echo "DELL not mounted" 
fi

Shell Variables

A shell variable can be set simply through the following:
> myvar=something
The value of a variable is used when the name is prefixed with a dollar sign:
> echo myvar   [prints myvar]
> echo $myvar  [prints something]

Within double quotes, values are substituted for shell variables. Within single quotes, they are not:

> echo "This is $myvar."   [prints This is something.]
> echo ’This is $myvar.’  [prints This is $myvar.]

Other Uses of Quotes

One major use of quotes on the command line is to allow blanks in an argument. For example,

> mycommand one two three
has three arguments, but
> mycommand "one two" three
has two. Either single or double quotes can be used for this purpose.

Another use is to prevent the shell from seeing characters that have special meaning. This sometimes works with double quotes and sometimes doesn’t— when in doubt, use single quotes, which always leave everything inside quotes “as is”. If quotes are not used, then special characters have to be “escaped” with a backslash to give them their actual meaning. For example:

> echo this;  [not this]   ***will not work
> echo ’this;  [not this]’  ***ok
> echo this\;\ \ \[not this\]   ***ok 
> echo this is an asterisk * and this isn’t  ***will not work
Quotes are often needed when a file name contains a space:
> cp myfile file two
> cp myfile file\ two
> cp myfile "file two"
> cd ’Program Files"

Shell Variable Substitution

Shell variables can be manipulated in various ways to get what you want. Here are a few examples:


> myfile="/home/dierdorf/myfile.ext"
> echo ${myfile}            prints /home/dierdorf/myfile.ext
> echo ${myfile#*/}         prints home/dierdorf/myfile.ext 
> echo ${myfile##*/}        prints myfile.ext
> echo ${myfile%.*}         prints /home/dierdorf/myfile
> echo ${myfile%%e*}        prints /hom
> echo ${${myfile%%.*}##*/} prints myfile
> echo ${myfile/my/your}    prints /home/dierdorf/yourfile.ext
> echo ${myfile/e/a/a}       prints /homa/diardorf/myfila.axt
The entire list of possibilities is on page 7 of the handout.

Using Logic

In the expression

part1 && part2
part2 is executed only if part1 is true; otherwise it is skipped. (Logical AND)
part1 || part2
causes part2 to be executed only if part1 is false. (Logical OR)
! part1
is true if part1 is false, and vice versa. (Logical NOT)

Anything inside [[ ... ]] is evaluated to be true or false. For example:

Putting It Together


> cat bin/unhtmlall

#! /bin/bash

shopt -s nullglob

echo "================="
for i  in "$@" 
do
    [[ ! -e "$i" ]] && continue
    cat "$i" | w3m -T text/html -dump >"${i%.htm*}.txt"
    dd="${i}_files"
    [[ -d "$dd" ]] && rm -r $dd
    dd="${i%.htm*}_files"
    [[ -d "$dd" ]] && rm -r $dd
    echo "$i --> ${i%.htm*}.txt"
done
rename s/\.txt\././ *.txt
echo "=================="

read -p "Delete all converted files? (yN) ==> " ANS
[[ $ANS == "y" ]] && rm "$@" 

Parentheses, Etc.

The shell has several grouping constructs that can cause major confusion until you figure them out:

[ ... ]
Logical true-false, based on return code of expression(s).
[[ ... ]]
Logical true-false, allows && and ||.
(( ... ))
Numerical evaluation.
{ ... }
Execute as a group in the current shell.
( ... )
Execute as a group in a subshell.
`...`
Old way to execute a command and substitute the result.
$(...)
New and better way to execute a command and substitute the result.

Command Line Helps

In addition to the fundamental job of running other programs on demand, modern shells all provide several other features for the user.

More, More, More

Most people customize their shell, selecting the prompt style they like, adding aliases, and setting options to change the default behavior. These customizations are normally in the file .bashrc (or .zshrc) in the user’s home directory. The number of settings is mind-boggling, and much too complex to go into here. The only one you need is adding ~/bin to PATH, as shown above. If you want to change things, here are some sources:

Last modified: Tue Aug 14 20:45:25 CDT 2012