A [Li|U]nix shell is the command-line interface between the user and the system. It is used to perform some action, specifically, typing commands and displaying output, requested by the user.
Bash is known as the Bourne-again shell, written by Brian Fox, and is a play on the name of the previously named Bourne shell (/bin/sh) written by Steve Bourne. 
Over time, as one progresses with using the shell, it will become necessary to execute commands that may contain many arguments or have output piped to other commands. Beyond simple commands such as cat and ls, it can be tedious should one need to re-type, or, in most cases, edit, a given command. Luckily, bash provides a facility to make this scenario easier: the command-line editing mode.
The command-line editing mode emulates the movement functions of two common text editors, emacs and vi. In the case of the shell, the cursor’s movement is being controlled.
Tighten up the above sentence. It’s wordy and doesn’t seem to make the point I want it to make.
By default, bash operates in emacs mode.
The following commands are very common while using the emacs mode.
The following commands are very common while using the vi mode.
Environment variables are used to define values for often-used attributes of a user’s shell. In total, these variables define the user’s environment. Some environment variables provide a simple value describing some basic attribute, such the user’s current directory ($PWD). Others define the behavior of a command, such as whether or not the history command should log repeated commands individually or log the repeated command once ($HISTCONTROL).
The most common, or most recognized, environment variable is the $PATH variable. It defines the set of directories that the shell can search to find a command. Without an explicit path provided when calling a command (i.e. /bin/ps), the shell will search the directories listed in the $PATH variable until it finds the command. If the command is not found in any of the defined directories in $PATH, the shell will produce an error explaining as much.
$ foobar -V -bash: foobar: command not found
To view the contents of the $PATH variable, use echo to print the variable’s value:
$ echo $PATH /usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
The order of the directories in the $PATH variable, from left to right, is important; when searching directories for a command, the shell will stop looking after it finds its first match. In other words, using our example $PATH variable above, if there is a version of ps that exists in /usr/local/bin that is preferred (by the sysadmin) over the version that exists in /bin, the shell will still execute /bin/ps due to the precedence of the directories defined in the $PATH variable.
To list all of the shell’s environment variables, use the env command:
$ env HOSTNAME=foobar SHELL=/bin/bash TERM=xterm HISTSIZE=1000 USER=root PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/bin MAIL=/var/spool/mail/root PWD=/root/curriculum PS1=[\[\e[33;1m\]\t \[\e[31;1m\]\u\[\e[0m\]@\[\e[31;1m\]\h\[\e[0m\] \W\[\e[0m\]]# HISTCONTROL=ignoredups SHLVL=1 SUDO_COMMAND=/bin/bash HOME=/root HISTTIMEFORMAT=[%Y-%m-%d %H:%M:%S] OLDPWD=/tmp
Shell profiles are used to define a user’s environment. In cases where an environment variable needs to be set or a script needs to be run at login, a profile can be used to ensure this happens consistently and automatically. Anything that can be run in a standalone shell script can be placed in a profile.
There are two types of profiles:
This is the global profile. Any environment variable set in this file applies to all users. Any script called from this file is executed for all users.
This is the user profile. Any environment variable set in this file applies to the user only. Any script called from this file is executed for the user only.
NOTE: It is possible to override settings from /etc/profile via ~/.bash_profile as ~/.bash_profile is executed after /etc/profile.
Certain variables exist that provide useful information about what is happening in the environment. For example, it may be necessary to know the ID of a running process or the exit status of an executed command.
To determine the process ID (PID) of the current shell, first run ps to find the PID, then run echo $$ to confirm the PID.
$ ps -efl | grep bash 502 20440 20439 0 10:25PM ttys001 0:00.01 -bash 4006 31 0 2433436 1228 - S 0 502 20447 20440 0 10:29PM ttys001 0:00.00 grep bash 4006 31 0 2432768 620 - R+ 0 $ echo $$ 20440
Occasionally, commands will need to be executed in the background (via the & operator). The PID of that process can be found using the $! variable. For example, call sleep for 30 seconds and place it in the background. Then echo $! to see the PID. Alternatively, call ps to confirm the PID.
$ sleep 30 &  20450 $ echo $! 20450 $ ps -efl | grep sleep 502 20450 20440 0 10:33PM ttys001 0:00.00 sleep 30 4006 31 0 2432748 496 - S 0
When a command is executed, it always has an exit status. That status defines whether or not the command was successful. For success, the exit status is 0. Non-zero values denote failure. Many commands provide multiple exit codes to help define what the reason for failure was. This helps the user troubleshoot any problems.
As an example, try to list a known file within a user’s home directory, then list a file that is known not to exist. After each command, execute echo $? to see the exit status.
$ ls .bash_profile .bash_profile $ echo $? 0 $ ls foobar ls: foobar: No such file or directory $ echo $? 1
The history is a handy facility within bash; it stores all of the commands that the user has executed.
To see the history, simply type history and all of the stored commands will be displayed to the terminal. Similarily, run cat ~/.bash_history to see all stored commands.
A benefit of storing command history is that the commands can be easily recalled. To execute the last command, type !!:
$ ls file1 file2 dir1 $ !! ls file1 file2 dir1
Note that the last command is echoed just above the output of that command.
To execute the nth command in history, run !n where n is the line number of the command as found in the output of history:
$ history | less 1 ls -la 2 ls -F 3 pwd $ !2 ls -F file1 file2 dir1/
Finally, one can search the history by typing Ctrl-r followed by a string to match a command:
$ (reverse-i-search)`ls': ls -F
To execute the command (if a match is found), simply type Enter.
From time to time, it may be necessary to manage commands running in the background. These are typically referred to as jobs. A command can be placed in the background via the & operator. Use the jobs command to see the job in the background. To bring it back to the foreground, run fg:
[23:24:22 ~]$ sleep 30 &  20969 [23:24:26 ~]$ jobs + Running sleep 30 & [23:24:29 ~]$ fg sleep 30 [23:24:56 ~]$
While in the foreground, the job can be suspended via Ctrl-z and sent to the background once more using bg:
[23:24:56 ~]$ sleep 30 &  21078 [23:28:25 ~]$ jobs + Running sleep 30 & [23:28:27 ~]$ fg sleep 30 ^Z + Stopped sleep 30 [23:28:33 ~]$ bg + sleep 30 & [23:28:37 ~]$ jobs + Running sleep 30 & [23:29:39 ~ ]$ jobs + Done sleep 30
It is possible to have multiple jobs running in the background at the same time. Use the jobs command to track them via their job ID, noted between the square brackets after sending a job to the background. Knowing the job ID is helpful in the event that the job needs to be pulled into the foreground (via fg) or if the job needs to be killed:
[23:36:01 ~]$ sleep 120 &  21086 [23:36:16 ~]$ sleep 240 &  21087 [23:36:20 ~]$ jobs - Running sleep 120 & + Running sleep 240 & [23:36:21 ~]$ fg %1 sleep 120 ^C [23:36:33 ~]$ jobs + Running sleep 240 & [23:36:35 ~]$ kill %2 [23:36:39 ~]$ jobs + Terminated: 15 sleep 240
NOTE: When manipulating jobs with any command, the jobs are described by their ID using the %n notation where n is the job ID.
|||C Programming by Al Stevens, Dr. Dobb’s Journal, July 1, 2001|