Christopher Aubergine Fraser
When you're entering Unix commands, you are in fact interacting with the shell. The shell is so named because it puts a layer between you and the
gooey, pulsating splatter that is at the heart of UNIX. Taking the time to
become accustomed to the ways of UNIXshells can save you from much tedium and
frustrationm, and also make you incredibly smart and 50
This chapter attempts to demystify the interactive aspects of shell
usage and gives an overview of the major features that are common to
more recent UNIXshells. It assumes readers are accustomed to basic
UNIXcommands.
A Unix shell works in a very simple way:
When you log into a Unix machine, the login program automatically
starts up a shell for you. There are a number of different shells
around. The type of shell started up is referred to as your default shell. This is determined by a field in your password file
entry. You can use the finger command to look up someone's
default shell. The following command should report that I use bash as my default shell.
There are two major lineages of Unix shells, the original Bourne shell
sh(1) and its bastard love child the C shell csh(1). From
these a number of bloated feature-ridden shells have
sprogged21.1. This document will deal with three of the shells
available at UTS:
Most, if not all, of the features discussed are available in the other
major Unix shells.
As mentioned above, a shell is simply an interactive Unix program, so
to play around with a shell, try running it. For example, to run bash, enter the command:21.3
Running the shell in this manner should be sufficient for trying out most
of the examples presented here. Eventually, after playing around with
a shell you may decide you want to use it all the time. See the
section on Changing Your Shell for further information.
All of the shells check to see if a startup file exists in the
users home directcory. This file contains a list of commands that
should be executed every time the shell starts up. Much of this
document will talk about commands you can use to customise aspects of
the shell. If you enter them at the prompt, they will only affect that
shell session. If you put them in your startup file they will affect
all new shell sessions.
The name of the startup file varies from shell to shell:21.4
This probably the most used interactive shell feature. First implemented in
csh, history substitution is also available in tcsh, bash
and zsh with slight flavour variations. It is most useful for
correcting typos in a previous command or reusing text from a previous
command line, without having to use your mouse to cut-and-paste.
The basic idea is that every command line entered is stored as an
entry in a history list. The number of entries in the history buffer
is determined by the environment variable HISTSIZE for bash and history for csh and tcsh. To view the
current history list, use the history command. After a few dozen
commands this list will become somewhat excessive, so it's typical to
pipe the output through a command like tail. Eg:
Or perhaps something more adventurous like:
Most people define their own command h to print out the last
couple of history commands. See the section on Functions and
Aliases further on.
After reading in your command line, the shell scans it for history phrases. A history phrase begins with a bang character (!)
and usually extends to next whitespace character21.5. If the shell understands your
phrase, it will replace the entire phrase with text from the command
buffer. The following sections explain how to specify exactly what
text you want from the history buffer.
The manual page for csh has a fairly succinct section on all of the
bells and whistles associated with history substitution. bash and
tcsh both offer obscure extensions.
Following the bang is text to indicate exactly which history entry you
want to reference. There are three basic forms:
For example:
If you only want part of the command line, you can select specific
words21.6 by appending a colon and a word
designator. The most commonly used designators are:
Here are Some quick examples. The command executed is printed under the
history phrase.
You can append additional colons and designators to modify the
substituted text. The most useful of these designators is :s/x/y
which substitutes occurrences of x with y. The following
example selects the previous entry and substitutes cc with hh.
A short form of this designator is available via the caret ^
character. Thus, an alternate formulation of the above is:
Note that the caret modifier only works on the previous history entry.
Caret is especially useful for fixing typos like transposed
characters. In bash at least there is also a :p modifier
which, if it appears at the end of a line, will result in the modified
line been printed but not executed. This is useful for checking to see
if the modifications were performed as intended. If acceptable, the
command line can then be executed with !!.
Interactive shells display a prompt to signify they are ready for
the next line of input. You can set your prompt to be any text string
that takes your fancy.21.7 In sh and bash you simply assign to the PS1 variable:
And in csh and tcsh you use the prompt environment
variable:
The text string will be evaluated before being set as the
prompt. This means you can refer to the output of commands and
other environment variables in the string. For example, to use the
output of the hostname command and the value of the LOGNAME environment variable in your prompt you can use
for bash and
for csh and tcsh. Note that because the prompt string is only
evaluated once, the above prompts are static (ie: they do not change).
This can lead to unexpected results. For example:
will display the current working directory you were in when you
changed the prompt, rather than the directory you're currently in. If you
change directory the prompt will not change.
Prompts are good place to print useful information. Suggestions include the
name of the machine you are logged into (the hostname), current working
directory and the current history number. Note that the latter two can
change as you execute commands. Now csh is pretty poor with regard to
useful prompts. The only way you can have the prompt updated after changing
the current working directory is to redefine the cd
command.21.8 The only really useful prompt
information csh easily provides is the current history number, which
is displayed by a
bash and tcsh support all manner of prompt fanciness. The
following table summaries the special codes you can put into the
prompt string and what they do;
tcsh and bash both have loads more special prompt codes,
most of which are just plain silly. Consult the manual page if you're
interested.
You can use different typefaces for your prompt. Most
terminals21.9 can handle VT100 control codes. As a quick example, the
following bash style prompt will be printed in bold:
Control characters can confuse line editing. Normally you can get
around this by splitting your prompt across two lines. A example of
such a two-line prompt is:21.10
The ``
The usefulness of Job Control has mostly been superseded by windows.
Job control evolved out of the desire to run multiple commands (or
``jobs'') from the one terminal. With the advent of windowing system,
you just start up another window. Still, you may not have that luxury if
you're remotely logged-in somehere.21.11
Commands started by the shell normally run in the foreground. This
means that the shell waits for them to finish before prompting for another
command. You can put a command into the background by putting an
ampersand (
Doing so will print out the job number the command was allocated (and
the process ID) and return you to the prompt. Each job the shell
starts has a job number associated with it. If you only ever run
commands in the foreground the shell will reuse job number 1 for all
of them. You can place a background job in the foreground
using the fg command, which accepts an optional argument of the
job number. If you omit the job number, it will foreground the most
recently backgrounded job.
You can suspend the foreground job using Control-Z, then put it in
background with the bg command. This is otherwise similar to the
fg command.
You can refer to jobs via the percent (
You can also get a list of the current jobs and their status, at least in
bash, by using the jobs built-in:
Shells differ in what they do about backgrounded jobs when you log out
of the shell. csh and tcsh will typically kill them unless
you run them via the nohup(1) command. bash leaves
backgrounded processes alone, but will warn about suspended jobs. Often,
system administrators get antsy about background processes which stay
running after their owner has logged out. Check first.
You have already met several characters, such as ! and
The tilde (~) character can be used to refer to the home directories of
other users. It must be at the start of a word---the text following the
tilde is interpreted as a username. The shell will find their home directory
using the password file. If you follow the tilde with a slash - or nothing
at all - it assumes you mean your own home directory.
Pathname expansion (or globbing as it is usually called)
attempts to interpret a word as a pattern. The word is replaced with a
list of pathnames - files and directories - which successfully match the
pattern. Note that in UNIX(unlike DOS), the shell actually performs the
globbing. This means that UNIXconsole programs all support globbing
automatically. You signify you want a word to be globbed by one of the
following characters:
As with most things presented here, the best way to get used to
globbing is to have a play with it. I recommend you initially use the
echo command to see exactly what the glob pattern is expanded
to.
Note that file names beginning with dot (.) are not normally globbed,
unless you explicitly include the dot yourself. There is a very good
reasons for this. The following command could potentially be
disastrous if .. was globbed.
In most flavours of Unix you cannot undelete21.12.
The brace characters ({ and }) are also special characters (in bash
at least). The following should illustrate their function.
Filename completion allows you to partially type the name of a file or command
and have the shell complete the rest.
To complete a filename, type the first few letters and hit TAB or
CTRLI. If you've used enough characters to distinguish your
file from all others in the directory, the shell will complete the
filename for you, otherwise it will ring the keyboard bell.
bash uses the GNU readline library to do its filename
completion. In the standard setup the TAB key works as above, but
hitting it a second time lists options. Readline can be configured
by a .inputrc file in your home directory. Apparently, you can
set TAB to cycle through your options, rather than listing them.
There is also a word (rather than pathname) completion option, based
on the last few hundred words you've typed in. Consult the bash
manual page for further information.
Filename completion is turned on in csh via:
The author is ignorant of filename completion in tcsh, but assumes it's
something similar to csh.
Most shells allow you to ignore certain file extensions. For bash this is set by the FIGNORE variable. The following will
make bash ignore files ending in .o and .out. Note
that they can still be globbed, only filename completion will ignore
them.
Both bash and tcsh have interactive command line editing. This
means you can use control keys (like the arrow keys) to edit a command as
you type it in. The default ``mode'' in bash and tcsh is for
emacs-style editing keys. See the appendix for a summary of these.
However, both shells also have a vi mode. To enable this in bash
put the following command in your .bashrc.
For tcsh the following should be placed in your .cshrc.
Aliases are a rather simplistic attempt to allow you to define new
commands or modify the behaviour of existing ones.
In csh and tcsh the alias command is also used to
define new aliases.
The first alias redefines the rm command to prompt for
confirmation before deleting. The second defines a command list
which uses ls and more. The
the shell would effectively execute the command:
bash uses a slightly different syntax for aliases. The above rm example would look like:
Note that bash does not support
The builtin command type can be used to view the definitions of
aliases and functions defined in bash. The manual page for bash contains complete information.
There are two ways of doing this. Firstly, leave your default shell as-is,
but have it automatically start a different shell after logging in. This is
achieved by adding the appropriate lines to the end of your shell startup
file. To automatically start up bash in this manner if your default
shell is csh:
The same idea can be used to start up tcsh from csh, but
it's a little bit more tricky since tcsh also uses the .cshrc file. If tcsh itself tries to startup tcsh you'll
end up in an infinite loop. This will not only prevent you from
logging onto the machine and fixing the problem, it will probably
bring the machine to its knees. It's worth noting that doing this
during assignment time is potentially life threatening21.13.
The second option is to change your default shell. This gives you
quicker logins than the first option, since csh no longer has to
be loaded, but it means that environment variables set by the Faculty of IT csh login files are not be passed to the new shell. You have to find
the important environment variables and set them yourself in your own
login file21.14. You can use the chsh command to change your default shell, however it is really only
worth doing if your are seriously going to use the additional features
of the new shell.
A Brief Description
% finger cfraser
Login name: cfraser In real life: Chris 'Aubergine' Fraser
Directory: /home/cfraser Shell: /usr/local/bin/bash
On since Feb 17 14:04:55 on console
A Forest of Shells
Try Before You Buy
% bash
bash$
Shell Startup
Shell
Startup File
csh/tcsh
.cshrc
sh
.profile
bash
.bashrc
zsh
.zshrc
History Substitution
% history | tail -20
% history | sed -e "s/^[ ]*/ /" -e "s/ / /" | /usr/5bin/pr -t -w80 -2
Selecting History Entries
% echo !50 # print out history entry 50
% !?login # execute the last entry referring to login
% !! > temp # execute the last entry and redirect output
% echo "The last ls command was: !ls"
Filtering Selections
% axe birthdays
% !!:0
axe
% vi !?bir:$ calendar
vi birthdays calendar
% emacs !!:*
emacs birthdays calendar
Modifying Selections
% !!:s/cc/hh/
% ^cc^hh^
Prompts
$ PS1="I Honk For Unicorns $ "
% set prompt = "I Honk For Unicorns % "
Evaluation
$ PS1="$LOGNAME@`hostname`$ "
% set prompt ="$LOGNAME@`hostname`% "
% set prompt = "`pwd`% "
More Usefulness
tcsh
bash
Function
History number
Host name
User name
Working Directory
Less Usefulness
$ PS1="\033[1m\w\033[0m\u@\h[\!] "
$ PS1="\033[1m\w\033[0m\n\u@\h[\!] "
Job Control
% kill %2
$ jobs
[1]+ Stopped jstar .bashrc
[2]- Running mpg123 mckc.mp3 &
Word Expansion
% echo 'Hello World!' # bang is quoted
% vi swallow\&hurl # ampersand is escaped
Tilde Expansion
% ls ~bigted # list the files in Big Ted's home directory
% ls ~/bin # list the files in your own bin directory
Pathname Expansion
% echo *.[ch] # show names of .c and .h files
% ls -l ../* # list files in parent directory
% vi */Makefile # edit the Makefile files in immediate subdirectories
% rm x? # remove all two letter files beginning with x
% rm [A-Z]* # remove all files starting with upper case letters
% rm -rf *
Brace Expansion
% echo aa{1,2,3}bb
aa1bb aa2bb aa3bb
% ls -d /usr/local/{bin,lib}
/usr/local/bin /usr/local/lib
Filename Completion
% set filec
$ FIGNORE=".o:.out"
Command Line Editing
set -o vi
bind vi
Functions and Aliases
% alias rm 'rm -i'
% alias list 'ls -la \!* | more'
!* expands to the list
of arguments given to the command. Thus, if you then entered:
% list /class/usr /users
% ls -la /class/usr /users | more
$ alias rm="rm -i"
!*. Instead, bash has
functions. These are similar to aliases but vastly more powerful.
Written as a function list looks like:
$ list() { ls -la $* | more }
Changing Your Shell
% cat >> ~/.cshrc
exec /usr/local/bin/bash
^D