|
The Console, Konsole, XTerm, etc
When you start the unix console on the Mac or Linux, that really is just a
window which knows how to display text in a fixed width font. It knows
nothing about commands or anything like that.
However, it knows that it must immediately start another process called a
shell, forward your keystrokes to that program and display any output the
shell sends back. It also knows that once that shell finishes, so should
it (usually anyway).
Shells
The Shell is the thing that directly executes your commands. Common
examples include tcsh, bash, zsh, ksh, ash,.... However, there are two
main styles: Korn Shells (bash is the main one) and C Shells (tcsh is the
main one). Windows shells are crap and do very little bar execute
commands. Good unix shells are full programming environments.
Shells read your commands, interpret them and react in the correct way.
So, when you type "ls -la skoleLinux" into the console this is what
happens:
- The console gets the keystrokes one at a time and passes them unchanged
to the shell program it is running.
- The shell reads the keystrokes. When it gets a <return>, it breaks
up the command as follows:
Word #1: "ls"
Word #2: "-la"
Word #3: "skoleLinux"
Word #1 is a command, the rest are options to the command. The command is
either
- a shell built-in command (echo,export,cd,=, ...)
- an external command (should be in PATH)
If the command is a built-in (eg cd skoleLinux), your shell does it
internally. Otherwise, it searches the PATH environment variable for a
program matching with that name. Here's
my PATH (and how to display it):
gavin@ravioli gavin> echo $PATH
/usr/local/bin:/bin:/usr/bin/X11:/usr/games:/home/gavin/bin
"ls" is not a built-in. So, it must be in the PATH. The above list of
directories is searched in order to find a program called "ls". The shell
finds the matching program "/bin/ls".
- Now, the shell executes "/bin/ls" passing it the options "-la" and
"skoleLinux". Until it completes "ls" is now in control.
The difference between one shell and another lies mostly in the details of the
interpretation and what built-in commands are available. The shells are
the main owners/maintainers of Environment variables (eg $PATH, $CVS_RSH,
$UID). One major difference between bash and tcsh is the built-in command
used to set/modify your environment variables.
In bash, to set an environment variable you do things like:
export PATH=/usr/local/bin:/usr/bin
export PATH=$PATH:/usr/bin/X11:/usr/games:/home/gavin/bin
echo $PATH
/usr/local/bin:/bin:/usr/bin/X11:/usr/games:/home/gavin/bin
In tcsh, you would do:
setenv PATH /usr/local/bin:/usr/bin
setenv PATH $PATH:/usr/bin/X11:/usr/games:/home/gavin/bin
echo $PATH
/usr/local/bin:/bin:/usr/bin/X11:/usr/games:/home/gavin/bin
I recommend using bash. It's the standard one, it's the one I use and
know and it's the one people will generally assume you are using as it is the
default in most Linux systems.
In most unix systems the command "chsh" will allow you to change your
shell permanently. You want it to be "/bin/bash" (without inverted
commas of course).
BASH
A few useful facts about bash:
- ~/.bash_profile (ie the file .bash_profile in your home dir)
All commands in this file are executed when you start bash. So you can
put customisations in there, such as setting environment variables. You
might like to create the file with:
export CVS_RSH=ssh
export CVS_ROOT=":ext:johne@cvs.skoleLinux.no:/var/lib/cvs"
the above commands would be executed every time you login. Then you
wouldn't need to type the commands every time you want to use CVS,
they'd be set every time in advance.
- alias
If you type a command a lot (eg ssh -X -C johne@fortycoats.ucd.ie):
you can create a shortcut by:
alias forty="ssh -t -X -C johne@fortycoats.ucd.ie "
so, from then on, every time you type "forty" on the command line, when
bash interprets it, it will substitute the above longer string delaying
your inevitable arthritis. This is something you would put in your
~/.bash_profile
- It's a full programming environment.
Without going into gory details, suffice to say that you can write
if, else, while, for, etc. directly into bash and it will interpret it.
For example, the following command will loop over a bunch of infidel
usernames, deleting their home directories.
for i in john rowland paul
do
rm -r ~$i/
done
- Wildcards and other special characters
If you do
ls foo_*.txt
you'll get a listing of all files beginning with "foo_" and ending
".txt" .
In DOS, you can similarly do dir * . However, in DOS, the dir
program reads the * and evaluates it. Here, BASH evaluates the * and ls
sees the list of files as its options. ls itself does not understand
wildcards.
When it interpets the command it looks for
certain special characters to interpret:
* means a sequence of one or more characters (a wildcard)
? means a single character (a wildcard)
$ means the following characters make up an env variable (eg $PATH)
[acde] means a single character matching any of a,c,d or e
[0-9] means any digit
~ shorthand for home directory
As a case in point, if you are ever in a directory with a huge number
of files (say 100,000) and you want to delete or list the files, you
might try:
gavin@robin tmp1> ls *
bash: /bin/ls: Argument list too long
gavin@robin tmp1> rm *
bash: /bin/rm: Argument list too long
It won't work. This is because bash evaluates the *, all 100,000
filenames end up as arguments (options) to the command and the
ls and rm programs can't handle this. One
solution which is certainly not optimal, but is useful as an example is
to use a for loop.
gavin@robin tmp1> for i in *
> do
> rm $i
> done
So bash launches the rm command once for each file * matches instead of
once for all files.
Related: Basic Shell Commands Moving to the last directory you were in
About the author, Gavin McCullagh.
|