Working in the shell it is often necessary to correct typing errors at the beginning of the line and it is now and then convenient to reuse commands that have been given before. The shell contains powerful editing mechanisms with arrow keys and control sequences (press the Ctrl-key and another key simultaneously) to make such changes simple and efficient. Use arrow-up to access an earlier command. The cursor is positioned on the line with arrow-left and arrow-right. The Insert key toggles (changes back and forth) between the default character-insert mode and character overwrite. The following control sequences are also useful:
C-a goto beginning of line
C-e goto end of line
C-d delete the character at the cursor
C-k delete (kill) to end of line
C-h (or backspace) delete character to the left of the cursor
Another mechanism that help improving the speed is the completion mechanism (invoked with the TAB character) that works both for commands and file names. Try $ cat /etc/hostn<TAB> to see how it works!
It is often convenient to refer to a whole group of files at the same time. The shell includes such a mechanism which is called wildcards. The most important ones are
* matches zero or more characters
? matches exactly one character
{abc,def} matches exactly one entire word from the options given
$ ls /dev/tty* $ ls /dev/tty? $ ls /dev/tty{a,b}{3,4} |
The file names in a Linux system may contain all kinds of characters except "/" and the null character (which means end of string). It is nevertheless wise to avoid certain charcters in file names since the shell assigns special meanings to them. These characters include "*", "$", "?", "!", " ", ";", "\", "|", "&", "~", "{", "}", "[", "]".
Some aspects of the behavior of shell are governed by environment variables. The command printenv shows a list of the environment variables. Some of these are:
USER=olsson SHELL=/bin/bash OSTYPE=linux HOME=/home/olsson TERM=xterm PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games PS1=Peter.Olsson$ |
$ MYVAR=myvalue |
$ echo $MYVAR myvalue |
$ export MYVAR |
$ export MYVAR=myvalue |
The most direct way to execute a command is to write the pathname of the command, e.g. /bin/ls. It is however also possible (and much more common, as in all our examples above) to only write a command name, e.g. ls. The connection between the command names and the path names for the files is through the PATH variable.
The PATH variable is a list of directories where the system looks for commands to be executed. One common setting is
PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games |
$ unset PATH $ ls bash: ls: No such file or directory |
The connection between the command name ls and the executable file (program) /bin/ls is shown by the which command:
$ which ls /bin/ls |
It is common for users to put their own commands in a directory like "/home/olsson/bin". To make these commands directly accessible as commands in the shell, just add "/home/olsson/bin" to the path:
$ export PATH=/home/olsson/bin:$PATH |
The standard prompt in bash is "bash-2.05b$". This is governed by the variable PS1. Change the prompt such that it shows your name:
bash-2.05b$ export PS1="Peter.Olsson$ " Peter.Olsson$ |
As discussed above there are good reasons to slightly adjust the behavior of the shell by changing the environment variables PATH and PS1. There are many more ways to customize the shell to fit ones own needs. Instead of manually giving these commands each time a shell is started those commands should be put into the initialization file ".bashrc" in the home directory, e.g. /home/olsson/.bashrc. One of the exercises with emacs will be to edit that file.
The concept process is central to UNIX systems. Note that program and process are different things:
A program is an executable file residing in a disk file.
An executing instance of a program is called a process.
$ ps -a PID TTY TIME CMD 4679 pts/2 00:00:00 bash 5071 pts/2 00:00:05 xterm 6373 pts/4 00:00:00 top 6374 pts/2 00:00:00 ps $ kill 6373 $ ps -a PID TTY TIME CMD 4679 pts/2 00:00:00 bash 5071 pts/2 00:00:05 xterm 6375 pts/2 00:00:00 ps |
The discussion and the examples above have illustrated that the actions we take in a shell have the effect to start a process. One remarkable thing is that the shell actually is an ordinary process itself with no special rights. An ordinary user can write a program to work as his own shell with whatever syntax he wants.
We only mention two aspects of job control:
Ctrl-c is used to kill a running process.
Ctrl-z is used to suspend the process currently running in the shell. This is e.g. useful when one has forgotten to put the "&" after a command that is to run in a separate window.
$ emacs Ctrl-z [1]+ Stopped emacs $ bg [1]+ emacs & |
The output from commands like cat or ls is usually written to standard output. There are however cases when one instead wants the output written to a file. One way to solve this would be to ask the program to open a file and direct the output to that file.
The Unix way of doing this is to instead let the shell handle the redirection, i.e. before executing the command, the shell opens the file. The command is then exectuted with standard output directed to the file. To illustrate this, we use the find command (which is a normally used with some of its many options; see the man page for a quick introduction.).
$ cd $ find . |
We now do the same but also redirect the output to the file find-output:
$ find . > find-output |
$ cat find-output |
This is now in general an unsorted list of files. To get the list ordered we can use the sort command that sorts line of input. We now redirect the input:
$ sort < find-output |
This is all very nice, but it is possible to take one more step. We can actually do without the file find-output and instead directly connect the output of find to the input of sort. That is called piping and is performed with the "|" symbol. The construct
$ find . | sort |
A simple way to change the behavior of the shell to fit you needs is by defining aliases. It could e.g. be good to be asked for a confirmation before the rm command actually does remove the file(s). That kind of behavior is given by "rm -i", but to make it happen each time you write rm define the alias
$ alias rm='rm -i' |
The alias with no argument lists the currently defined aliases and unalias deletes the alias.