Chapter 11. The Interactivebash Shell

CONTENTS

Chapter 11. The Interactive bash Shell

  •  11.1 Introduction
  •  11.2 Command Line Shortcuts
  •  11.3 Variables
  •  BASH SHELL LAB EXERCISES

graphics/ch11.gif

11.1 Introduction

With an interactive shell, the standard input, output, and error are tied to a terminal. When using the Bourne Again (bash) shell interactively, you type UNIX commands at the bash prompt and wait for a response. Bash provides you with a large assortment of built-in commands and command line shortcuts, such as history, aliases, file and command completion, command line editing, and many more. Some of the features were present in the standard UNIX Bourne shell but the GNU project has expanded the shell to include a number of new features as well adding POSIX compliancy. With the release of bash 2.x, so many features of the UNIX Korn shell and C shell have been included that the bash shell is a fully functional shell at both the interactive and programming level, while upwardly compatible with the standard Bourne shell. For UNIX users, bash offers an alternative to the standard shells, sh, csh, and ksh.[1]

This chapter focuses on how you interact with bash at the command line and how to customize your working environment. You will learn how to take advantage of all shortcuts and built-in features in order to create an efficient and fun working environment. The next chapter takes you a step further. Then you will be ready to write bash shell scripts to further tailor the working environment for yourself by automating everyday tasks and developing sophisticated scripts, and if you are an administrator, doing the same not only for yourself but also for whole groups of users.

11.1.1 Versions of bash

The Bourne Again shell is a Capricorn, born on January 10, 1988, fathered by Brian Fox and later adopted by Chet Ramey, who now officially maintains bash, enhances it, and fixes bugs. The first version of bash was 0.99. The current version (as of this writing) is version 2.04. Major enhancements were completed in version 2.0, but there are a num ber of operating systems that are still using version 1.14.7. All versions are freely available under the GNU public license. To see what version you are using, use the - -version option to bash or print the value of the BASH_VERSION environment variable.

Example 11.1
$ bash --version GNU bash, version 2.03.0(1)-release (sparc-sun-solaris) Copyright 1998 Free Software Foundation, Inc. $ echo $BASH_VERSION 2.03.0(1)-release 

11.1.2 Startup

If the bash shell is your login shell, it follows a chain of processes before you see a shell prompt.[2]

Figure 11.1. Starting the bash shell.

graphics/11fig01.gif

When the system boots, the first process to run is called init, PID #1. It spawns a getty process. This process opens up the terminal ports, providing a place where standard input comes from and a place where standard output and errors go, and puts a login prompt on your screen. The /bin/login program is then executed. The login program prompts for a password, encrypts and verifies the password, sets up an initial environment, and starts up the login shell, /bin/bash, the last entry in the passwd file. The bash process looks for the system file, /etc/profile, and executes its commands. It then looks in the user's home directory for an initialization file called .bash_profile. After executing commands from bash _profile, [3] it will execute a command from the user's ENV file, usually called .bashrc, and finally the default dollar sign ($) prompt appears on your screen and the shell waits for commands. (For more on initialization files, see "The Environment".)

Changing the Shell at the Command Line. If you want to start another shell from the command line temporarily (without changing the /etc/passwd file), just type the name of the shell. For example, if you are currently using the standard Bourne shell and would rather have bash as your shell, you can change the shell at the command line simply by typing bash.

Example 11.2
1   $ ps     PID   TTY    TIME   CMD     1574  pts/6  0:00   sh 2   $ bash     bash-2.03$ 3   bash-2.03$ ps     PID   TTY    TIME    CMD     1574  pts/6  0:00    sh     1576  pts/6  0:00    bash 

EXPLANATION

  1. The output of the ps command shows what processes are running. Currently, sh (the Bourne shell) is running.

  2. At the Bourne shell prompt, the user enters bash and starts up the Bourne Again shell. A new prompt appears.

  3. At the bash prompt, the ps command is executed. The output shows that two shells are running and the current shell is now bash.

11.1.3 The Environment

The environment of a process consists of variables, open files, the current working directory, functions, resource limits, signals, and so forth. It defines those features that are inherited from one shell to the next and the configuration for the working environment. The configuration for the user's shell is defined in the shell initialization files.

The Initialization Files. The bash shell has a number of startup files that are sourced. Sourcing a file causes all settings in the file to become part of the current shell; i.e., a subshell is not created. (The source command is discussed in "The source or dot Command" on page 621.) The initialization files are sourced depending on the whether the shell is a login shell, an interactive shell (but not the login shell), or a noninteractive shell (a shell script).

When you log on, before the shell prompt appears, the systemwide initialization file, etc/profile, is sourced. Next, if it exists, the .bash_profile in the user's home directory is sourced. It sets the user's aliases and functions and then sets user-specific environment variables and startup scripts.

If the user doesn't have a .bash_profile, but does have a file called .bash_login, that file will be sourced, and if he doesn't have a .bash_login, but does have a .profile, it will be sourced. (The .bash_login file is similar to the C shell's .login file and the .profile is normally sourced by the Bourne shell when it starts up.)

Here is a summary of the order that bash processes its initialization files [4] (see figure 11.2):

Figure 11.2. Order of processing initialization files.

graphics/11fig02.gif

if /etc/profile exists, source it,    if ~/.bash_profile exists, source it,       if  ~/.bashrc exists, source it,    else if ~/.bash_login exists, source it,    else if ~/.profile exists, source it. 

The /etc/profile File. The /etc/profile file is a systemwide initialization file set up by the system administrator to perform tasks when the user logs on. It is executed when the bash shell starts up. It is also available to all Bourne and Korn shell users on the system and normally performs such tasks as checking the mail spooler for new mail and displaying the message of the day from the /etc/motd file. (The following examples will make more sense after you have completed this chapter.)

Example 11.3
(Sample /etc/profile) # /etc/profile # Systemwide environment and startup programs # Functions and aliases go in /etc/bashrc 1  PATH="$PATH:/usr/X11R6/bin" 2  PS1="[\u@\h \W]\\$ " 3  ulimit -c 1000000 4  if [ 'id -gn' = 'id -un' -a 'id -u' -gt 14 ]; then 5    umask 002    else      umask 022    fi 6  USER='id -un' 7  LOGNAME=$USER 8  MAIL="/var/spool/mail/$USER" 9  HOSTNAME='/bin/hostname' 10 HISTSIZE=1000 11 HISTFILESIZE=1000 12 export PATH PS1 HOSTNAME HISTSIZE HISTFILESIZE USER LOGNAME MAIL 13  for i in /etc/profile.d/*.sh ; do 14      if [ -x $i ]; then 15           . $i         fi 16  done 17  unset i # 

EXPLANATION

  1. The PATH variable is assigned locations where the shell should search for commands.

  2. The primary prompt is assigned. It will be displayed in the shell window as the user's name (\u),the @ symbol, the host machine (\W), and a dollar sign.

  3. The ulimit command (a shell built-in command) is set to limit the maximum size of core files created to 1,000,000 bytes. Core files are memory dumps of programs that have crashed, and they take up a lot of disk space.

  4. This line reads, if the user's group name is equal to the user's name and the user's ID number is greater than 14 (see 5)

  5. Then set the umask to 002. When directories are created they will get 775 permissions and files will get 664 permissions. Otherwise, the umask is set to 022, giving 755 to directories and 644 to files.

  6. The USER variable is assigned the username (id -un).

  7. The LOGNAME variable is set to the value in $USER.

  8. The MAIL variable is assigned the path to the mail spooler where the user's mail is saved.

  9. The HOSTNAME variable is assigned the name of the user's host machine.

  10. The HISTSIZE variable is set to 1000. HISTSIZE controls the number of history items that are remembered (from the history list stored in the shell's memory) and saved in the history file after the shell exits.

  11. The HISTFILESIZE is set to limit the number of commands stored in the history file to 1000, i.e., the history file is truncated after it reaches 1,000 lines. (See "History".)

  12. These variables are exported so that they will be available in subshells and child processes.

  13. For each file (ending in .sh) in the etc/profile.d directory (see 14)

  14. Check to see if the file is executable, and if it is (see 15)

  15. Execute (source) the file with the dot command. The files in the /etc/profile.d directory: lang.sh and mc.sh, respectively, set the character and font sets and create a function called mc that starts up a visual/browser file manager program called Midnight Commander. To see how the file manager works, type mc at the bash prompt.

  16. The done keyword marks the end of the for loop.

  17. The variable i is unset, i.e., removed from shell's name space. The value of i is whatever was assigned to it while in the for loop, if anything was assigned at all.

The ~/.bash_profile File. If the ~/.bash_profile is found in the user's home directory, it is sourced after the /etc/profile. If ~/.bash_profile doesn't exist, bash will look for another user-defined file, ~./bash_login, and source it, and if ~./bash_login doesn't exist, it will source the ~/.profile, if it exists. Only one of the three files (~/.bash_profile, ~/.bash_login, or ~/.profile) will be sourced. Bash will also check to see if the user has a .bashrc file and then source it.

Example 11.4
(Sample .bash_profile)     # .bash_profile     # The file is sourced by bash only when the user logs on.     # Get the aliases and functions 1   if [ -f ~/.bashrc ]; then 2           . ~/.bashrc     fi     # User-specific environment and startup programs 3   PATH=$PATH:$HOME/bin 4   ENV=$HOME/.bashrc     # or BASH_ENV=$HOME/.bashrc 5   USERNAME="root" 6   export USERNAME ENV PATH 7   mesg n 8   if [ $TERM = linux ]     then            startx    # Start the X Window system     fi 

EXPLANATION

  1. If there is a file called .bashrc in the user's home directory (see 2)

  2. Execute (source) the .bashrc file for the login shell.

  3. The PATH variable is appended with a path to the user's bin directory, normally the place where shell scripts are stored.

  4. The BASH_ENV[a] (ENV) file is set to the pathname for the .bashrc file, an initialization file that will be sourced for interactive bash shells and scripts only if the BASH_ENV (ENV) variable is set. The .bashrc file contains user-defined aliases and functions.

  5. The variable USERNAME is set to root.

  6. The variables are exported so that they are available to subshells and other processes will know about them.

  7. The mesg command is executed with the n option, disallowing others to write to the terminal.

  8. If the value of the TERM variable is linux, then startx will start the X window system (the graphical user interface allowing multiple virtual consoles), rather than starting an interactive session in the Linux console window. Because the ~/.bash_profile is only sourced when you log in, the login shell would be the best place to start up your X windows session.

[a] BASH_ENV is used by versions of bash starting at 2.0.

The BASH_ENV (ENV) Variable. Before bash version 2.0, the BASH_ENV file was simply called the ENV file (same as in Korn shell). The BASH_ENV (ENV) variable is set in the ~/.bash_profile. It is assigned the name of a file that will be executed every time an interactive bash shell or bash script is started. The BASH_ENV (ENV) file will contain special bash variables and aliases. The name is conventionally .bashrc, but you can call it anything you want. The BASH_ENV (ENV) file is not processed when the privileged option is on (bash -p or set -o privileged) or the - -norc command line option is used (bash -norc or bash - -norc [bash 2.x +]).

The .bashrc File. The BASH_ENV (ENV) variable is assigned (by convention) the name .bashrc. This file is automatically sourced every time a new or interactive bash shell or bash script starts. It contains settings that pertain only to the bash shell.

Example 11.5
(Sample .bashrc) # If the .bashrc file exists, it is in the user's home directory. # It contains aliases (nicknames for commands) and user-defined # functions. # .bashrc # User-specific aliases and functions 1   set -o vi 2   set -o noclobber 3   set -o ignoreeof 4   alias rm='rm -i'     alias cp='cp -i'     alias mv='mv -i' 5   stty erase ^h    # Source global definitions 6  if [ -f /etc/bashrc ]; then       . /etc/bashrc    fi 7   case "$-" in 8      *i*) echo This is an interactive bash shell                ;; 9      *)   echo This shell is noninteractive                ;;     esac 10  history_control=ignoredups 11  function cd { builtin cd $1; echo $PWD; } 

EXPLANATION

  1. The set command with the -o switch turns on or off special built-in options. (See "The set -o Options" on page 610.) If the switch is -o, a minus sign, the option is turned on, and if a plus sign, the option is turned off. The vi option allows interactive command line editing. For example, set -o vi turns on interactive command-line editing, whereas set vi +o turns it off. (See Table 11.1.)

  2. The noclobber option is turned on, which prevents the user from overwriting files when using redirection; e.g., sort filex > filex. (See "Standard I/O and Redirection".)

  3. When exiting a shell, normally you can type ^D (Control-D). With ignoreeof set, you must type exit.

  4. The alias for rm, rm -i, causes rm to be interactive (-i ), i.e., it will ask the user if it's OK to remove files before actually removing them.The alias for the cp, cp -i, command causes the copy to be interactive.

  5. The stty command is used to set the terminal backspace key to erase. ^H represents the Backspace key.

  6. If a file called /etc/bashrc exists, source it.

  7. If the shell is interactive, the special variable, $-, will contain an i. If not, you are probably running a script. The case command evaluates $-.

  8. If the value returned from $- matches *i*, i.e., any string containing an i, then the shell prints This is an interactive shell.

  9. Otherwise, the shell prints This shell is noninteractive. If you start up a script, or a new shell at the prompt, you will be able to tell whether or not your shell is interactive. It is only here to let you test your understanding of the terms "interactive" and "noninteractive" shell.

  10. The history_control setting is used to control how commands are saved in the history file. This line says, Don't save commands in the history file if they're already there.; i.e., ignore duplicates.

  11. This is a user-defined function. When the user changes directories, the present working directory, PWD, is printed. The function is named cd and contains within its definition, the command cd. The special built-in command, called builtin, precedes the cd command within the function definition to prevent the function from going into an infinite recursion; i.e., from calling itself indefinitely.

The /etc/bashrc File. Systemwide functions and aliases can be set in the /etc/bashrc file. The primary prompt is often set here.

Example 11.6
 (Sample /etc/bashrc)     # Systemwide functions and aliases     # Environment stuff goes in /etc/profile     # For some unknown reason bash refuses to inherit     # PS1 in some circumstances that I can't figure out.     # Putting PS1 here ensures that it gets loaded every time. 1   PS1="[\u@\h \W]\\$ " 2   alias which="type -path" 

EXPLANATION

  1. Systemwide functions and aliases are set here. The primary bash prompt is set to the name of the user (\u), and @ symbol, the host machine (\h), the basename of the current working directory, and a dollar sign. (See Table 11.2 .) This prompt will appear for all interactive shells.

  2. Aliases, nicknames for commands, are usually set in the user's .bashrc file. The alias was preset and is available when bash starts up. You use it when you want to find out where a program resides on disk; i.e., what directory it is found in; e.g., which ls will print /bin/ls.

The ~/.profile File. The .profile file is a user-defined initialization file. It is found in the user's home directory, and sourced once at login if running sh (Bourne shell). If running bash, .profile will be run if bash cannot find any other of the initialization files listed above. It allows a user to customize and modify his shell environment. Environment and terminal settings are normally put here, and if a window application or database application is to be initiated, it is started here.

Example 11.7
(Sample .profile) # A login initialization file sourced when running as sh or the #.bash_profile or .bash_login are not found. 1  TERM=xterm 2  HOSTNAME='uname -n' 3  EDITOR=/bin/vi 4  PATH=/bin:/usr/ucb:/usr/bin:/usr/local:/etc:/bin:/usr/bin:. 5  PS1="$HOSTNAME $ > " 6  export TERM HOSTNAME EDITOR PATH PS1 7  stty erase ^h 8  go () { cd $1; PS1='pwd'; PS1='basename $PS1'; } 9  trap '$HOME/.logout' EXIT 10 clear 

EXPLANATION

  1. The TERM variable is assigned the value of the terminal type, xterm.

  2. Because the uname -n command is enclosed in backquotes, the shell will perform command substitution, i.e., the output of the command (the name of the host machine) will be assigned to the variable HOSTNAME.

  3. The EDITOR variable is assigned /bin/vi. Programs such as mail and history will now have this variable available when defining an editor.

  4. The PATH variable is assigned the directory entries that the shell searches in order to find a UNIX program. If, for example, you type ls, the shell will search the PATH until it finds that program in one of the listed directories. If it never finds the program, the shell will tell you so.

  5. The primary prompt is assigned the value of HOSTNAME, the machine name, and the $ and > symbols.

  6. All of the variables listed are exported. They will be known by child processes started from this shell.

  7. The stty command sets terminal options. The Erase key is set to ^H, so that when you press the Backspace key, the letter typed preceding the cursor is erased.

  8. A function called go is defined. The purpose of this function is to take one argument, a directory name, cd to that directory, and set the primary prompt to the present working directory. The basename command removes all but the last entry of the path. The prompt will show you the current directory.

  9. The trap command is a signal handling command. When you exit the shell, that is, log out, the .logout file will be executed. The .logout file is a user-defined file containing commands that will be executed just before logging out, commands that will clean up temp files or log the time of log out, etc.

  10. The clear command clears the screen.

The ~/.bash-logout File. When the user logs out (exits the login shell), if a file called ~/.bash_logout exists, it is sourced. This file normally contains commands to clean up temporary files, truncate the history file, record the time of logout, etc.

Options to Prevent Startup Files from Being Executed. If bash is invoked with the - -noprofile option (e.g., bash - -noprofile), then the /etc/profile, ~/.bash_profile, ~/.bash_login, or ~/.profile startup files will not be sourced.

If invoked with the -p option (e.g., bash -p), bash will not read the user's ~/.profile file.

If bash is invoked as sh (Bourne shell), it tries to mimic the behavior of the Bourne shell as closely as possible. For a login shell, it attempts to source only /etc/profile and ~/.profile, in that order. The -noprofile option may still be used to disable this behavior. If the shell is invoked as sh, it does not attempt to source any other startup files.

The .inputrc File. Another default initalization file, .inputrc, is also read when bash starts up. This file, if it exists in the user's home directory, contains variables to customize keystroke behavior and settings that bind strings, macros, and control functions to keys. The names for the key bindings and what they do are found in the Readline library, a library that is used by applications that manipulate text. The bindings are used particularly by the built-in emacs and vi editors, when performing command line editing. (See "Command Line Editing" on page 641 for more on readline.)

11.1.4 Setting bash Options with the Built-In set and shopt Commands

The set -o Options. The set command can take options when the -o switch is used. Options allow you to customize the shell environment. They are either on or off, and are normally set in the BASH_ENV (ENV) file. Many of the options for the set command are set with an abbreviated form. For example, set -o noclobber can also be written, set -C. (See Table 11.1.)

Table 11.1. The Built-In set Command Options
Name of Option Shortcut Switch What It Does
allexport -a Automatically marks new or modified variables for export from the time the option is set, until unset.
braceexpand -B Enables brace expansion, and is a default setting.
emacs   For command line editing, uses the emacs built-in editor, and is a default setting.
errexit -e If a command returns a nonzero exit status (fails), exits. Not set when reading initialization files.
histexpand -H Enables ! and !! when performing history substitution, and is a default setting.
history   Enables command line history; on by default.
ignoreeof   Disables EOF (Control-D) from exiting a shell; must type exit. Same as setting shell variable, IGNOREEOF=10.
keyword -k Places keyword arguments in the environment for a command.
interactive-comments   For interactive shells, a leading # is used to comment out any text remaining on the line.
monitor -m Allows job control.
noclobber -C Protects files from being overwritten when redirection is used.
noexec -n Reads commands, but does not execute them. Used to check the syntax of scripts. Not on when running interactively.
noglob -d Disables pathname expansion; i.e., turns off wildcards.
notify -b Notifies user when background job finishes.
nounset -u Displays an error when expanding a variable that has not been set.
onecmd -t Exit after reading and executing one command.
physical -P If set, does not follow symbolic links when typing cd or pwd. The physical directory is used instead.
posix   Shell behavior is changed if the default operation doesn't match the POSIX standard.
privileged -p When set, the shell does not read the .profile or ENV file and shell functions are not inherited from the environment; automatically set for setuid scripts.
posix   Change the default behavior to POSIX 1003.2.
verbose -v Turns on the verbose mode for debugging.
vi   For command line editing, uses the vi built-in editor.
xtrace -x Turns on the echo mode for debugging.

 

FORMAT

set -o option  # Turns on the option. set +o option  # Turns off the option. set -[a-z]  # Abbreviation for an option; the minus turns it on. set +[a-z]  # Abbreviation for an option; the plus turns it off. 
Example 11.8
1   set -o allexport 2   set +o allexport 3   set -a 4   set +a 

EXPLANATION

  1. Sets the allexport option. This option causes all variables to be automatically exported to subshells.

  2. Unsets the allexport option. All variables will now be local in the current shell.

  3. Sets the allexport option. Same as 1. Not every option has an abbreviation. (See Table 11.1.)

  4. Unsets the allexport option. Same as 2.

Example 11.9
1 $ set -o   braceexpand    on   errexit        off   hashall        on   histexpand     on   keyword        off   monitor        on   noclobber      off   noexec         off   noglob         off   notify         off   nounset        off   onecmd         off   physical       off   privileged     off   verbose        off   xtrace         off   history        on   ignoreeof      off   interactive-comments on   posix          off   emacs          off   vi             on 2  $ set -o noclobber 3  $ date > outfile 4  $ ls > outfile    bash: outfile: Cannot clobber existing file. 5  $ set +o noclobber 6  $ ls > outfile 7  $ set -C 

EXPLANATION

  1. With the -o option, the set command lists all the options currently set or not set.

  2. To set an option, the -o option is used. The noclobber option is set. It protects you from overwriting files when using redirection. Without noclobber, the file to the right of the > symbol is truncated if it exists, and created if it doesn't exist.

  3. The output of the UNIX date command is redirected to a file called outfile.

  4. This time, the outfile exists. By attempting to redirect the output of ls to outfile, the shell complains that the file already exists. Without noclobber set, it would be clobbered.

  5. With the +o option to the set command, noclobber is turned off.

  6. This time, trying to overwrite outfile is fine because noclobber is no longer set.

  7. Using the -C switch to the set command is an alternate way of turning on noclobber. +C would turn it off.

The shopt Built-In (Version 2.x+). The shopt (shell options) built-in command is used in newer versions of bash as an alternative to the set command. In many ways shopt duplicates the set built-in command, but it adds more options for configuring the shell. See Table 11.27 for a list of all the shopt options. In the following example, shopt with the -p option prints all the available options settings. The -u switch indicates an unset option and -s indicates one that is currently set.

Example 11.10
1   $ shopt -p     shopt -u cdable_vars     shopt -u cdspell     shopt -u checkhash     shopt -u checkwinsize     shopt -s cmdhist     shopt -u dotglob     shopt -u execfail     shopt -s expand_aliases     shopt -u extglob     shopt -u histreedit     shopt -u histappend     shopt -u histverify     shopt -s hostcomplete     shopt -u huponexit     shopt -s interactive_comments     shopt -u lithist     shopt -u mailwarn     shopt -u nocaseglob     shopt -u nullglob     shopt -s promptvars     shopt -u restricted_shell     shopt -u shift_verbose     shopt -s sourcepath 2   $ shopt -s cdspell 3   $ shopt -p cdspell     shopt -s cdspell 4   $ cd /hame     /home 5   $ pwd     /home 6   $ cd /ur/lcal/ban     /usr/local/man 7   $ shopt -u cdspell 8   $ shopt -p cdspell     shopt -u cdspell 

EXPLANATION

  1. With the -p (print) option, the shopt command lists all settable shell options and their current values, either set (-s) or unset (-u).

  2. With the -s option, shopt sets (or turns on) an option. The cdspell option causes the shell to correct minor spelling errors on directory names given as arguments to the cd command. It will correct simple typos, insert missing letters, and even transpose letters if it can.

  3. With the -p option and the name of the option, shopt indicates whether the option is set. The option has been set (-s).

  4. In this example, the user tries to cd to his home directory, but misspells home. The shell fixes the spelling; i.e., hame becomes home. The directory is changed to /home.

  5. The output of the pwd command displays the current working directory, showing that the directory was really changed even though the user spelled it wrong.

  6. This time the directory name is missing letters and has a misspelling for the last entry, ban. The shell makes a pretty good attempt to spell out the correct pathname by inserting the missing letters, and correcting ban to man. Because the b in ban is the first misspelled character, the shell searches in the directory for an entry that might end with a and n. It finds man.

  7. With the -u switch[a], shopt unsets (or turns off ) the option.

  8. With the -p switch and the name of the option, shopt indicates whether the option is set. The cdspell option has been unset (-u).

[a] The words switch or option are interchangeable. They are arguments to a command that contain a leading dash.

11.1.5 The Prompts

When used interactively, the shell prompts you for input. When you see the prompt, you know that you can start typing commands. The bash shell provides four prompts: the primary prompt is a dollar sign ($), and the secondary prompt is a right angle bracket symbol (>). The third and fourth prompts, PS3 and PS4 respectively, will be discussed later. The prompts are displayed when the shell is running interactively. You can change these prompts.

The variable PS1 is set to a string containing the primary prompt. Its value, the dollar sign, appears when you log on and waits for user input, normally a UNIX command. The variable PS2 is the secondary prompt, initially set to the right angle bracket character (>). It appears if you have partially typed a command and then pressed Enter. You can change the primary and secondary prompts.

The Primary Prompt. The dollar sign (or bash $) is the default primary prompt. You can change your prompt. Normally prompts are defined in /etc/bashrc or the user initialization file, .bash_profile, or .profile (Bourne shell).

Example 11.11
1   $ PS1="$(uname -n) > " 2   chargers > 

EXPLANATION

  1. The default primary prompt is a dollar sign (bash $). The PS1 prompt is being reset to the name of the machine[a](uname -n) and a > symbol.

  2. The new prompt is displayed.

[a] The command, uname -n, is executed because it is enclosed in a set of parentheses preceded by a dollar sign. An alternative would be to enclose the command in backquotes. See "Command Substitution".)

Setting the Prompt with Special Escape Sequences. By inserting special backslash/escape sequences into the prompt string, you can customize the prompts. Table 11.2 lists the special sequences.

Table 11.2. Prompt String Settings
Backslash Sequence What It Evaluates To
\t The current time in HH:MM:SS format.
\d The date in "Weekday Month Date" format (e.g., Tue May 26).
\n Newline.
\s The name of the shell, the basename of $0 (the portion following the final slash).
\w The current working directory.
\W The basename of the current working directory.
\u The username of the current user.
\h The hostname.
\# The command number of this command.
\! The history number of this command.
\$ If the effective UID is 0, a #, otherwise a $.
\nnn The character corresponding to the octal number nnn.
\\ Backslash.
\[ Begin a sequence of nonprinting characters; could be used to embed a terminal control sequence into the prompt.
\] End a sequence of nonprinting characters.
New in bash Version 2.x+:
\a The ASCII bell character.
\@ The current time in 12-hour AM/PM format.
\H The hostname.
\T The current time in 12-hour format: HH:MM:SS.
\e The ASCII escape character (033).
\v The version of bash, e.g., 2.03.
\V The release and pathlevel of bash; e.g., 2.03.0.
Example 11.12
1   $  PS1="[\u@\h \W]\\$ "     [ellie@homebound ellie]$ 2   $  PS1="\W:\d> "     ellie:Tue May 18> 

EXPLANATION

  1. You customize the primary bash prompt using special backslash/escape sequences. \u evaluates to the user's login name, \h to the host machine, and \W is the basename for the current working directory. There are two backslashes. The first backslash escapes the second backslash, resulting in \$. The dollar sign is protected from shell interpretation and thus printed literally.

  2. The primary prompt is assigned \W, the escape sequence evaluating to the basename of the current working directory, and \d, the escape sequence evaluating to today's date.

The Secondary Prompt. The PS2 variable is assigned a string called the secondary prompt. Its value is displayed to standard error, which is the screen by default. This prompt appears when you have not completed a command or more input is expected. The default secondary prompt is >.

Example 11.13
1   $ echo "Hello 2   > there" 3   Hello     there 4   $ 5   $ PS2="----> " 6   $ echo 'Hi 7   ------>     ------>     ------>there'      Hi     there     $ 8 $ PS2="\s:PS2 > "   $ echo 'Hello    bash:PS2 > what are    bash:PS2 > you    bash:PS2 > trying to do?    bash:PS2 > '    Hello    what are    you    trying to do? $ 

EXPLANATION

  1. The double quotes must be matched after the string "Hello.

  2. When a newline is entered, the secondary prompt appears. Until the closing double quotes are entered, the secondary prompt will be displayed.

  3. The output of the echo command is displayed.

  4. The primary prompt is displayed.

  5. The secondary prompt is reset.

  6. The single quote must be matched after the string 'Hi.

  7. When a newline is entered, the new secondary prompt appears. Until the closing single quote is entered, the secondary prompt will be displayed.

  8. The PS2 prompt is set to the name of the shell (\s) followed by a string consisting of a colon, PS2 and >, followed by a space.

The Search Path. Bash uses the PATH variable to locate commands typed at the command line. The path is a colon-separated list of directories used by the shell when searching for commands. The default path is system-dependent, and is set by the administrator who installs bash. The path is searched from left to right. The dot at the end of the path represents the current working directory. If the command is not found in any of the directories listed in the path, the shell sends to standard error the message filename: not found. The path is normally set in the .bash_profile if running the bash shell or .profile file if using sh, the Bourne shell.

If the dot is not included in the path and you are executing a command or script from the current working directory, the name of the script must be preceded with a ./, such as ./program_name, so that shell can find the program.

Example 11.14
(Printing the PATH) 1   $ echo $PATH     /usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:. (Setting the PATH) 2   $ PATH=$HOME:/usr/ucb:/usr:/usr/bin:/usr/local/bin: 3   $ export PATH 4   $ runit     bash: runit: command not found 5   $ ./runit     < program starts running here > 

EXPLANATION

  1. By echoing $PATH, the value of the PATH variable is displayed. The path consists of a list of colon-separated elements and is searched from left to right. The dot at the end of the path represents the user's current working directory.

  2. To set the path, a list of colon-separated directories are assigned to the PATH variable. Note that in this path, the dot is not at the end of the path, perhaps as a security measure.

  3. By exporting the path, child processes will have access to it. It is not necessary to export the PATH on a separate line: It could be written as follows: export PATH=$HOME:/usr/ucb:/bin:., etc., on the same line.

  4. Because the dot is not in the search path, when the runit program is executed in the present working directory, bash can't find it.

  5. Because the program name is preceded with a dot and a slash (./), the shell will be able to find it, and execute it, if it is the current working directory.

The hash Command. The hash command controls the internal hash table used by the shell to improve efficiency in searching for commands. Instead of searching the path each time a command is entered, the first time you type a command, the shell uses the search path to find the command, and then stores it in a table in the shell's memory. The next time you use the same command, the shell uses the hash table to find it. This makes it much faster to access a command than having to search the complete path. If you know that you will be using a command often, you can add the command to the hash table. You can also remove commands from the table. The output of the hash command displays the number of times the shell has used the table to find a command (hits) and the full pathname of the command. The hash command with the -r option clears the hash table. An argument of - - disables option checking for the rest of the arguments. Hashing is automatically implemented by bash. Although you can turn it off, if there isn't any compelling reason to do so, don't.

Example 11.15
(Printing the PATH) (Command line) 1   hash     hits   command     1      /usr/bin/mesg     4      /usr/bin/man     2      /bin/ls 2   hash -r 3   hash     No commands in hash table 4   hash find     hits    command     0       /usr/bin/find 

EXPLANATION

  1. The hash command displays the full pathname of commands that have been executed in this login session.(Built-in commands are not listed) The number of hits is the number of times the hash table has been used to find the command.

  2. The -r option to the hash command erases all remembered locations in the hash table.

  3. After the -r option was used in the last command, the hash command reports that there are no commands currently in the table.

  4. If you know you are going to use a command often, you can add it to the hash table by giving it as an argument to the hash command. The find command has been added. The table has zero hits because the command hasn't been used yet.

The source or dot Command. The source command (from the C shell) is a built-in bash shell command. The dot command, simply a period, (from the Bourne shell) is another name for source. Both commands take a scriptname as an argument. The script will be executed in the environment of the current shell; that is, a child process will not be started. All variables set in the script will become part of the current shell's environment. Likewise, all variables set in the current shell will become part of the script's environment. The source (or dot) command is normally used to reexecute any of the initialization files, e.g., .bash_profile, .profile, etc, if they have been modified. For example, if one of the settings, such as the EDITOR or TERM variable, has been changed in the .bash_profile since you logged on, you can use the source command to reexecute commands in the .bash_profile without logging out and then logging back on. A file, such as .bash_profile, or for that matter any shell script, does not need execute permissions to be sourced with either the dot or the source commands.

Example 11.16
$ source .bash_profile $ . .bash_profile 

EXPLANATION

The source or dot command executes the initialization file, .bash_profile, within the context of the current shell. Local and global variables are redefined within this shell. The dot command makes it unnecessary to log out and then log back in again after the file has been modified.[a]

[a] If the .bash_profile were executed directly as a script, a child shell would be started. Then the variables would be set in the child shell, and when the child shell exited, the parent shell would not have any of the settings available to it.

11.1.6 The Command Line

After you log on, the bash shell displays its primary prompt, a dollar sign by default. The shell is your command interpreter. When the shell is running interactively, it reads commands from the terminal and breaks the command line into words. A command line consists of one or more words (or tokens), separated by whitespace (blanks and/or tabs), and terminated with a newline, generated by pressing the Enter key. The first word is the command, and subsequent words are the command's arguments. The command may be a UNIX executable program such as ls or date, a user-defined function, a built-in command such as cd or pwd, or a shell script. The command may contain special characters, called metacharacters, which the shell must interpret while parsing the command line. If a command line is too long, the backslash character, followed by a newline, will allow you to continue typing on the next line. The secondary prompt will appear until the command line is terminated.

The Order of Processing Commands. The first word on the command line is the command to be executed. The command may be a keyword, an alias, a function, a special built-in command or utility, an executable program, or a shell script. The command is executed according to its type in the following order:

  1. Aliases

  2. Keywords (such as if, function, while, until)

  3. Functions

  4. Built-in commands

  5. Executables and scripts

Special built-in commands and functions are defined within the shell, and therefore are executed from within the context of the current shell, making them much faster in execution. Scripts and executable programs such as ls and date are stored on disk, and the shell, in order to execute them, must first locate them within the directory hierarchy by searching the PATH environment variable; the shell then forks a new shell that executes the script. To find out the type of command you are using i.e., a built-in command, an alias, a function, or an executable, etc. use the built-in type command. (See Example 11.17.)

Example 11.17
$ type pwd pwd is a shell builtin $ type test test is a shell builtin $ type clear clear is /usr/bin/clear $ type m m is aliased to 'more' $ type bc bc is /usr/bin/bc $ type if if is a shell keyword $ type -path cal /usr/bin/cal $ type which which is aliased to 'type -path' $ type greetings greetings is a function greetings () {        echo "Welcome to my world!"; } 

Built-In Commands and the help Command. Built-in commands are commands that are part of the internal source code for the shell. They are built-in and readily available to the shell, whereas commands such as date, cal, and finger are compiled binary programs that reside on the disk. There is less overhead in executing a built-in because it involves no disk operations. Built-in commands are executed by the shell before the programs on disk. Bash has added a new online help system so that you can see all the built-ins, or a description for a particular built-in; help itself is a built-in command. See Table 11.28 for a complete list of built-in commands.

Example 11.18
1   $ help help     help: help [pattern ...]     Display helpful information about built-in commands. if PATTERN     is specified, gives detailed help on all commands matching     PATTERN, otherwise a list of the built-ins is printed. 2   $ help pw     pwd: pwd         Print the current working directory. 

Changing the Order of Command Line Processing. Bash provides three built-in commands that can override the order of command line processing: command, builtin, and enable.

The command built-in eliminates aliases and functions from being looked up in the order of processing. Only built-ins and executables, found in the search path, will be processed.

The builtin command looks up only built-ins, ignoring functions and executables found in the path.

The enable built-in command turns built-ins on and off. By default, built-ins are enabled. Disabling a built-in allows an executable command found on the disk to be to be executed without specifying a full pathname, even if it has the same name as a built-in. (In normal processing, bash searches for built-ins before disk executable commands.) Built-ins become disabled by using the -n switch. For example, a classic confusion for new shell programmers is naming a script test. Because test is a built-in command, the shell will try to execute it rather than the user's script (a built-in is normally executed before any executable program). By typing: enable -n test, the test built-in is disabled, and the user's script will take precedence.

Without options, the enable built-in prints a list of all the built-ins. Each of the following built-ins are described in "Shell Built-In Commands".

Example 11.19
1   $ enable     enable .     enable :     enable [     enable alias     enable bg     enable bind     enable break     enable builtin     enable cd     enable command     enable continue     enable declare     enable dirs         .....     enable read     enable readonly     enable return     enable set     enable shift     enable shopt        .....     enable type     enable typeset     enable ulimit     enable umask     enable unalias     enable unset     enable wait 2   enable -n test 3   function cd { builtin cd; echo $PWD; } 

EXPLANATION

  1. The enable built-in, without any options, displays a complete list of all bash shell built-in commands. This example shows just part of that list.

  2. With the -n switch, the test built-in command is disabled. Now, you execute your script named test without worrying about the built-in test being executed instead. It's not good practice to name a script by the same name as an operating system command, because if you try to run the same script in another shell, the disabling of built-ins doesn't exist.

  3. The function is called cd. The builtin command causes the cd within the function definition to be called instead of the function cd, which would cause an endless recursive loop.

The Exit Status. After a command or program terminates, it returns an exit status to the parent process. The exit status is a number between 0 and 255. By convention, when a program exits, if the status returned is zero, the command was successful in its execution. When the exit status is nonzero, the command failed in some way. If a command is not found by the shell, the exit status returned is 127. If a fatal signal causes the command to terminate, the exit status is 128 plus the value of the signal that caused it to die.

The shell status variable, ?, is set to the value of the exit status of the last command that was executed. Success or failure of a program is determined by the programmer who wrote the program.

Example 11.20
1   $ grep ellie /etc/passwd     ellie:MrHJEFd2YpkJY:501:501::/home/ellie:/bin/bash 2   $ echo $?     0 3   $ grep nicky /etc/passwd 4   $ echo $?     1 5   $ grep ellie /junk     grep: /junk: No such file or directory 6   $ echo $?     2 7   $ grip ellie /etc/passwd     bash: grip: command not found 8   $ echo $?     127 9   $ find / -name core ^C    User presses Control-C 10  $ echo $?     130 

EXPLANATION

  1. The grep program searches for the pattern ellie in the /etc/passwd file and is successful. The line from /etc/passwd is displayed.

  2. The ? variable is set to the exit value of the grep command. Zero indicates successful status.

  3. The grep program cannot find user nicky in the /etc/passwd file.

  4. The grep program cannot find the pattern; the ? variable return value is nonzero. An exit status of 1 indicates failure.

  5. The grep fails because the /junk file cannot be opened.The grep error message is sent to standard error, the screen.

  6. If grep cannot find the file, it returns an exit status of 2.

  7. The grip command is not found by the shell.

  8. Because the command is not found, the exit status, 127, is returned.

  9. The find command is interrupted when the SIGINT signal is sent by pressing Control-C. The signal number for Ctrl-C is 2.

  10. The status returned from a process that has been killed is 128 + the number of the signal; i.e., 128 + 2.

Multiple Commands at the Command Line. A command line can consist of multiple commands. Each command is separated by a semicolon, and the command line is terminated with a newline. The exit status is that of the last command in the chain of commands.

Example 11.21
$ ls; pwd; date 

EXPLANATION

The commands are executed from left to right, one after the other, until the newline is reached.

Grouping Commands. Commands may also be grouped so that all of the output is either piped to another command or redirected to a file.

Example 11.22
$ ( ls; pwd; date ) > outputfile 

EXPLANATION

The output of each of the commands is sent to the file called outputfile. The spaces inside the parentheses are necessary.

Conditional Execution of Commands. With conditional execution, two command strings are separated by the special metacharacters, double ampersands (&&) and double vertical bars (||). The command on the right of either of these metacharacters will or will not be executed based on the exit condition of the command on the left.

Example 11.23
$ cc prgm1.c -o prgm1 && prgm1 

EXPLANATION

If the first command is successful (has a zero exit status), the command after the && is executed; i.e., if the cc program can successfully compile prgm1.c, the resulting executable program, prgm1, will be executed.

Example 11.24
$ cc prog.c >& err || mail bob < err 

EXPLANATION

If the first command fails (has a nonzero exit status), the command after the || is executed; i.e., if the cc program cannot compile prog.c, the errors are sent to a file called err, and user bob will be mailed the err file.

Commands in the Background. Normally, when you execute a command, it runs in the foreground, and the prompt does not reappear until the command has completed execution. It is not always convenient to wait for the command to complete. When you place an ampersand (&) at the end of the command line, the shell will return the shell prompt immediately and execute the command in the background concurrently. You do not have to wait to start up another command. The output from a background job will be sent to the screen as it processes. Therefore, if you intend to run a command in the background, the output of that command might be redirected to a file or piped to another device, such as a printer, so that the output does not interfere with what you are doing.

The ! variable contains the PID number of the last job put in the background. (See "Job Control" for more on background processing.)

Example 11.25
1   $ man sh | lp& 2   [1] 1557 3   $ kill -9 $! 

EXPLANATION

  1. The output of the man command (the manual pages for the UNIX command) is piped to the printer. The ampersand at the end of the command line puts the job in the background.

  2. There are two numbers that appear on the screen: the number in square brackets indicates that this is the first job to be placed in the background; the second number is the PID, or the process identification number of this job.

  3. The shell prompt appears immediately. While your program is running in the background, the shell is waiting for another command in the foreground. The ! variable evaluates to the PID of the job most recently put in the background. If you get it in time, you will kill this job before it goes to the print queue.

11.1.7 Job Control

Job control is a powerful feature of the bash shell that allows you to selectivly run programs, called jobs, in the background or foreground. A running program is called a process or a job and each process has a process ID number, called the PID. Normally, a command typed at the command line is running in the foreground and will continue until it has finished unless you send a signal by pressing Ctrl-C or Ctrl-\ to terminate it. With job control you can send a job to the background and let it keep running; you can stop a job by pressing Ctrl-Z, which sends the job to the background and suspends it; you can cause a stopped job to run in the background; you can bring a background job back to the foreground; and you can even kill the jobs you have running in the background or foreground. For a list of job commands, see Table 11.3.

By default, job control is already set (some older versions of UNIX do not support this feature). If disabled, it can be reset by any one of the following commands:

FORMAT

set -m           # set job control in the .bashrc file set -o monitor   # set job control in the .bashrc file bash -m -i       # set job control when invoking interactive bash 
Example 11.26
1   $ vi     [1]+  Stopped     vi 2   $ sleep 25&     [2] 4538 3   $ jobs     [2]+  Running     sleep 25&     [1]-  Stopped       vi 4   $ jobs -l     [2]+ 4538   Running      sleep 25&     [1]- 4537   Stopped        vi 5   $ jobs %%     [2]+ 4538   Running       sleep 25& 6   $ fg %1 7   $ jobs -x echo %1     4537 8   $ kill %1         # or  kill 4537     [1]+   Stopped      vi     Vim: Caught deadly signal TERM     Vim: Finished.     [1]+   Exit 1      vi 

EXPLANATION

  1. After the vi editor is invoked, you can press ^Z (Control-Z) to suspend the vi session. The editor will be suspended in the background, and after the message Stopped appears, the shell prompt will appear immediately.

  2. The ampersand at the end of the command causes the sleep command, with an argument of 25, to execute in the background. The notation [2] means that this is the second job to be run in the background and the PID of this job is 4538.

  3. The jobs command displays the jobs currently in the background.

  4. The jobs command with the -l option displays the processes (jobs) running in the background and the PID numbers of those jobs.

  5. The %% argument causes jobs to display the most recent command put in the job table.

  6. The fg command followed by a percent sign and the job number will bring that numbered job into the foreground. Without a number, fg brings the most recently backgrounded job back into the foreground.

  7. The -x option can be used to print just the PID number of the job. %1 refers to the vi session that was stopped in the first example.

  8. The kill command sends a TERM signal to the process and kills it. The vi program is killed. You can specify either the job number or the PID number as arguments to the kill command.

 

Table 11.3. Job Control Commands
Command Meaning
jobs Lists all the jobs running.
^Z (Ctrl-Z) Stops (suspends) the job; the prompt appears on the screen.
bg Starts running the stopped job in the background.
fg Brings a background job to the foreground.
stop Suspends a background job.
stty tostop Suspends a background job if it sends output to the terminal.
kill Sends the kill signal to a specified job.
wait [n] Waits for a specified job and returns its exit status, where n is a PID or job number.

 

Argument to jobs command Represents
%n Job number n.
%sting Job name starting with string.
%?string Job name containing string.
%% Current job.
%+ Current job.
%- Previous job, before current job.
-r Lists all running jobs.
-s Lists all suspended jobs.

New jobs Options. Two new options were added to the jobs command in bash versions 2.x. They are the -r and -s options. The -r option lists all running jobs, and the -s option lists all stopped jobs.

The disown Built-In. The disown built-in command (bash 2.x) removes a specified job from the job table. After the job has been removed, the shell will no longer recognize it as a viable job process and it can only be referenced by its process ID number.

11.2 Command Line Shortcuts

11.2.1 Command and Filename Completion

To save typing, bash implements command and filename completion, a mechanism that allows you to type part of a command or filename, press the Tab key, and the rest of the word will be completed for you.

If you type the first letters in a command and press the Tab key, bash will attempt to complete the command and execute it. If bash cannot complete the filename or command, because neither exists, the terminal may beep and the cursor will stay at the end of the command. If there is more than one command starting with those characters and you press the Tab key a second time, all commands that start with those characters will be listed.

If there are several files starting with the same letters, bash will complete the shortest name that matches, expand out the filename until the characters differ, and then flash the cursor for you to complete the rest.

Example 11.27
1   $ ls     file1 file2 foo foobarckle fumble 2   $ ls fu[tab]       # Expands to filename to fumble 3   $ ls fx[tab]       # Terminal beeps, nothing happens 4   $ ls fi[tab]       # Expands to file_  (_ is a cursor) 5   $ ls fi[tab][tab]  # Lists all possibilities     file1 file2 6   $ ls foob[tab]     # Expands to foobarckle 7   $ da[tab]          # Completes the date command     date     Tue Feb 28 18:53:40 PST 2001 8   $ ca[tab][tab]      # Lists all commands starting with ca     cal    captoinfo  case   cat 

EXPLANATION

  1. All files are listed for the current working directory.

  2. After fu is typed, the Tab key is pressed, causing the spelling of the filename to be completed to fumble, and listed.

  3. Because none of the files start with fx, the terminal beeps and the cursor remains but does nothing. (The terminal may not beep if that feature has been disabled.)

  4. There are a number of files starting with fi; the filenames are completed until the letters are no longer the same. If another Tab key is pressed, all files with that spelling are listed.

  5. By pressing two Tab keys, a list of all files beginning with file is printed.

  6. When the Tab key is pressed, the filename is expanded to foobarckle.

  7. When the Tab key is pressed after da, the only command that begins with da is the date command. The command name is expanded and executed.

  8. When the Tab key is pressed after ca, nothing happens because more than one command starts with ca. Pressing the Tab key twice lists all commands starting with ca.

11.2.2 History

The history mechanism keeps a history list, a numbered record of the commands that you have typed at the command line. During a login session, the commands you type are stored in the the shell's memory in a history list and then appended to the history file when you exit. You can recall a command from the history list and reexecute it without retyping the command. The history built-in command displays the history list. The default name for the history file is .bash_history, and it is located in your home directory.

When bash starts accessing the history file, the HISTSIZE variable specifies how many commands can be copied from the history file into the history list. The default size is 500. The HISTFILE variable specifies the name of the command history file (~/.bash_history is the default) where commands are stored. If unset, the command history is not saved when an interactive shell exits.

The history file grows from one login session to the next. The HISTFILESIZE variable controls the maximum number of lines contained in the history file. When this variable is assigned a value, the history file is truncated when it surpasses that number of lines. The default size is 500.

The fc -l command can be used to display or edit commands in the history list.

Table 11.4. History Variables
FCEDIT The pathname of the UNIX editor that uses the fc command.
HISTCMD The history number, or index in the history list, of the current command. If HISTCMD is unset, it loses its special properties, even if it is subsequently reset.
HISTCONTROL If set to a value of ignorespace, lines that begin with a space character are not entered on the history list. If set to a value of ignoredups, lines matching the last history line are not entered. A value of ignoreboth combines the two options. If unset, or if set to any other value than those above, all lines read by the parser are saved on the history list.
HISTFILE Specifies file in which to store command history. The default value is ~/.bash_history. If unset, the command history is not saved when an interactive shell exits.
HISTFILESIZE The maximum number of lines contained in the history file. When this variable is assigned a value, the history file is truncated, if necessary, to contain no more than that number of lines. The default value is 500.
HISTIGNORE A colon-separated list of patterns used to decide which command lines should be saved on the history list. Each pattern is anchored to the beginning of the line and consists of normal shell pattern matching characters. An & can be used in the pattern causing the history command to ignore duplicates; e.g., ty??:& would match for any command line starting with ty followed by two characters, and any duplicates of that command. Those commands would not be placed in the history list.
HISTSIZE The number of commands to remember in the command history. The default value is 500.

11.2.3 Accessing Commands from the History File

The Arrow Keys. To access commands from the history file, you can use the arrow keys on the keyboard to move up and down through the history file, and from left to right. You can edit any of the lines from the history file by using the standard keys for deleting, updating, backspacing, etc. As soon as you have edited the line, pressing the Enter key will cause the command line to be reexecuted.

Table 11.5. The Arrow Keys
Up arrow moves up the history list.
Down arrow moves down the history list.
Right arrow moves cursor to right on history command.
Left arrow moves left on history command.

The history Built-In Command. The history built-in command displays the history of commands typed preceded by an event number.

Example 11.28
1   $ history     982  ls     983  for i in 1 2 3     984  do     985  echo $i     986  done     987  echo $i     988  man xterm     989  adfasdfasdfadfasdfasdfadfasdfasdf     990  id -gn     991  id -un     992  id -u     993  man id     994  more /etc/passwd     995  man ulimit     996  man bash     997  man baswh     998  man bash     999  history     1000  history 

EXPLANATION

  1. The built-in history command displays a list of numbered commands from the history list. Any lines listed with an * have been modified.

The fc Command. The fc command, also called the fix command, can be used in two ways: (1) to select commands from the history list, and (2) to edit the commands in either the vi or emacs editor, or for that matter, any editor on your system.

In the first form, fc with the -l option can select specific lines or ranges of lines from the history list. When the -l switch is on, the output goes to the screen. For example, fc -l, the default, prints the last 16 lines from the history list, fc -l 10 selects lines numbered 10 through the end of the list, and fc -l -3 selects the last three lines. The -n switch turns off the numbering of commands in the history list. With this option on, you could select a range of commands and redirect them to a file, which in turn could be executed as a shell script. The -r switch reverses the order of the commands.

The second form of fc is described in "Command Line Editing" on page 641.

Table 11.6. The fc Command
fc Argument Meaning
-e editor Puts history list into editor.
-l n-m Lists commands in range from n to m.
-n Turns off numbering of history list.
-r Reverses the order of the history list.
-s string Accesses command starting with string.
Example 11.29
1  $ fc -l    4       ls    5       history    6       exit    7       history    8       ls    9       pwd   10       clear   11       cal 2000   12       history   13       vi file   14       history   15       ls -l   16       date   17       more file   18       echo a b c d   19       cd   20       history 2 $ fc -l -3   19       cd   20       history   21       fc -l 3 $  fc -ln          exit          history          ls          pwd          clear          cal 2000          history          vi file          history          ls -l          date          more file          echo a b c d          cd          history          fc -l          fc -l -3 4 $ fc -ln -3 > saved 5 $ more saved          fc -l          fc -l -3          fc -ln 6 $ fc -l 15   15       ls -l   16       date   17       more file   18       echo a b c d   19       cd   20       history   21       fc -l   22       fc -l -3   23       fc -ln   24       fc -ln -3 > saved   25       more saved   26       history 7 $ fc -l 15 20   15       ls -l   16       date   17       more file   18       echo a b c d   19       cd   20       history 

EXPLANATION

  1. fc -l selects the last 16 commands from the history list.

  2. fc -l -3 selects the last three commands from the history list.

  3. fc with the -ln options prints the history list without line numbers.

  4. The last three commands, without line numbers, from the history list are redirected to a file called saved.

  5. The contents of the file saved are displayed.

  6. Commands from the history list, starting at number 15, are listed.

  7. Commands numbered 15 through 20 are displayed.

If fc is given the -s option, a string pattern can be used to reexecute a previous command; e.g., fc -s rm will cause the most previous line containing the pattern rm to be reexecuted. To emulate the Korn shell's redo command, you can create a bash alias called r, e.g., alias r='fc -s' so that if you type r vi at the command line, the last history item containing that pattern will be reexecuted; in this case, the vi editor will be started just as it was the last time it started, including any arguments passed.

Example 11.30
1   $ history     1    ls     2    pwd     3    clear     4    cal 2000     5    history     6    ls -l     7    date     8    more file     9    echo a b c d 2   $ fc -s da     date     Thu Jul  15 12:33:25 PST 2001 3   $ alias r="fc -s" 4   $ date +%T     18:12:32 5   $ r d     date +%T     18:13:19 

EXPLANATION

  1. The built-in history command displays the history list.

  2. fc with the -s option searches for the last command that began with string da. The date command is found in the history list and is reexecuted.

  3. An alias (a user-defined nickname) called r is assigned the command fc -s. This means that any time r is typed at the command line, it will be substituted with fc -s.

  4. The date command is executed. It will print the current time.

  5. The alias is used as a shortcut to the fs -s command. The last command beginning with a d is reexecuted.

Reexecuting History Commands (bang! bang!). To reexecute a command from the history list, the exclamation point (called bang) is used. If you type two exclamation points (!!) bang, bang, the last command in the history list is reexecuted. If you type an exclamation point, followed by a number, the command listed by that number is reexecuted. If you type an exclamation point and a letter or string, the last command that started with that letter or string is reexecuted. The caret (^) is also used as a shortcut method for editing the previous command. See Table 11.7 for a complete list of history substitution characters.

Table 11.7. Substitution and History
Event Designator Meaning
! Indicates the start of history substitution.
!! Reexecutes the previous command.
!N Reexecutes the Nth command from the history list.
!-N Reexecutes the Nth command back from present command.
!string Reexecutes the last command starting with string.
!?string? Reexecutes the last command containing string.
!?string?% Reexecutes the most recent command line argument from the history list containing string.
!$ Uses the last argument from the last history command in the current command line.
!! string Appends string to the previous command and executes.
!N string Appends string to Nth command in history list and executes.
!N:s/old/new/ In previous Nth command, substitutes the first occurrence of old string with new string.
!N:gs/old/new/ In previous Nth command, globally substitutes old string with new string.
^old^new^ In last history command, substitutes old string with new string.
command !N:wn Executes current command appending an argument (wn) from the Nth previous command. Wn is a number starting at 0, 1, 2, designating the number of the word from the previous command; word 0 is the command itself, and 1 is its first argument, etc. (See Example 11.32.)
Example 11.31
1   $ date     Mon Jul  12 12:27:35 PST 2001 2   $ !!     date     Mon Jul  12 12:28:25 PST 2001 3   $ !106     date     Mon Jul  12 12:29:26 PST 2001 4   $ !d     date     Mon Jul  12 12:30:09 PST 2001 5   $ dare     dare: Command not found. 6   $ ^r^t     date     Mon Jul  12 12:33:25 PST 2001 

EXPLANATION

  1. The UNIX date command is executed at the command line. The history list is updated. This is the last command on the list.

  2. The !! (bang bang) gets the last command from the history list; the command is reexecuted.

  3. Command number 106 from the history list is reexecuted.

  4. The last command on the history list that started with the letter d is reexecuted.

  5. The command is mistyped. It should be date, not dare.

  6. The carets are used to substitute letters from the last command on the history list. The first occurrence of an r is replaced with a t; i.e., dare becomes date.

Example 11.32
1   $ ls  file1 file2 file3     file1 file2 file3     $ vi !:1     vi file1 2   $ ls file1 file2 file     file1 file2 file3     $ ls !:2     ls file2     file2 3   $ ls file1 file2 file3     $ ls  !:3     ls file3     file3 4   $ echo a b c     a b c     $ echo !$     echo c     c 5   $ echo a b c     a b c     $ echo !^     echo a     a 6   % echo a b c     a b c     % echo !*     echo a b c     a b c 7   % !!:p     echo a b c 

EXPLANATION

  1. The ls command lists file1, file2, and file3. The history list is updated. The command line is broken into words, starting with word number zero. If the word number is preceded by a colon, that word can be extracted from the history list. The !:1 notation means, get the first argument from the last command on the history list and replace it in the command string. The first argument from the last command is file1. (Word 0 is the command itself.)

  2. The !:2 is replaced with the second argument of the last command, file2, and given as an argument to ls. file2 is printed. (file2 is the third word.)

  3. ls !:3 reads, go to the last command on the history list and get the fourth word (words start at zero) and pass it to the ls command as an argument. (file3 is the fourth word.)

  4. The bang (!) with the dollar sign ($) refers to the last argument of the last command on the history list. The last argument is c.

  5. The caret (^) represents the first argument after the command. The bang (!) with the ^ refers to the first argument of the last command on the history list. The first argument of the last command is a.

  6. The asterisk (*) represents all arguments after the command. The ! with the * refers to all of the arguments of the last command on the history list.

  7. The last command from the history list is printed but not executed. The history list is updated. You could now perform caret substitutions on that line.

Command Line Editing. The bash shell provides two built-in editors, emacs and vi, that allow you to interactively edit your history list. When you use the editing features at the command line, whether in vi or emacs mode, the readline functions determine which keys will perform certain functions. For example, if using emacs, Ctrl-P allows you to scroll upward in the command line history, whereas if using vi, the K key moves upward through the history list. Readline also controls the arrow keys, cursor movement, changing, deleting, inserting text, and redoing or undoing corrections. Another feature of readline is the completion feature previously discussed in "Command and Filename Completion". This allows you to type part of a command, filename, or variable, and then, by pressing the Tab key, the rest of the word is completed. There are many more features provided by the Readline library designed to help manipulate text at the command line.

The emacs built-in editor is the default built-in editor and is modeless, whereas the vi built-in editor works in two modes, one to execute commands on lines and the other to enter text. If you use UNIX, you are probably familiar with at least one of these editors. To enable the vi editor, add the set command listed below[5] and put this line in your ~/.bashrc file. To set vi, type what's shown in the following example, at either the prompt or in the ~/.bashrc file.

Example 11.33
set -o vi 

EXPLANATION

Sets the built-in vi editor for command line editing of the history list.

To switch to the emacs editor, type:

Example 11.34
set -o emacs 

EXPLANATION

Sets the built-in emacs editor for command line editing of the history list.

The vi Built-In Editor. To edit the history list, go to the command line and press the Esc key. Then press the K key if you want to scroll upward in the history list, and the J key[6] to move downward, just like standard vi motion keys. When you find the command that you want to edit, use the standard keys that you would use in vi for moving left and right, deleting, inserting, and changing text. (See Table 11.8.) After making the edit, press the Enter key. The command will be executed and added to the bottom of the history list.

Table 11.8. vi Commands
Command Function
Moving Through the History File:
Esc k or + Move up the history list.
Esc j or - Move down the history list.
G Move to first line in history file.
5G Move to fifth command in history file for string.
/string Search upward through history file.
? String search downward through history file.
Moving Around on a Line:
h Move left on a line.
l Move right on a line.
b Move backward a word.
e or w Move forward a word.
^ or 0 Move to beginning of first character on the line.
$ Move to end of line.
Editing with vi:
a A Append text.
i I Insert text.
dd dw x Delete text into a buffer (line, word, or character).
cc C Change text.
u U Undo.
yy Y Yank (copy a line into buffer).
p P Put yanked or deleted line down below or above the line.
r R Replace a letter or any amount of text on a line.

The emacs Built-In Editor. If using the emacs built-in editor, like vi, start at the command line. To start moving upward through the history file, press ^P. To move down, press ^N. Use emacs editing commands to change or correct text, then press Enter and the command will be reexecuted. See Table 11.9.

Table 11.9. emacs Commands
Command Function
Ctrl-P Move up history file.
Ctrl-N Move down history file.
Ctrl-B Move backward one character.
Ctrl-R Search backward for string.
Esc B Move backward one word.
Ctrl-F Move forward one character.
Esc F Move forward one word.
Ctrl-A Move to the beginning of the line.
Ctrl-E Move to the end of the line.
Esc < Move to the first line of the history file.
Esc > Move to the last line of the history file.
Editing with emacs:
Ctrl-U Delete the line.
Ctrl-Y Put the line back.
Ctrl-K Delete from cursor to the end line.
Ctrl-D Delete a letter.
Esc D Delete one word forward.
Esc H Delete one word backward.
Esc space Set a mark at cursor position.
Ctrl-X Ctrl-X Exchange cursor and mark.
Ctrl-P Ctrl-Y Push region from cursor to mark into a buffer (Ctrl-P) and put it down (Ctrl-Y).

FCEDIT and Editing Commands. If the fc command is given the -e option followed by the name of a UNIX editor, that editor is invoked containing history commands selected from the history list; e.g., fc -e vi -1 -3 will invoke the vi editor, create a temporary file in /tmp, with the last three commands from the history list in the vi buffer. The commands can be edited or commented out. (Preceding the command with a # will comment it.) If the user quits the editor, the commands will all be echoed and executed.[7]

If the editor name is not given, the value of the FCEDIT variable is used (typically set in the initialization files, either bash_profile or .profile), and the value of the EDITOR variable is used if FCEDIT is not set. When editing is complete, and you exit the editor, all of the edited commands are echoed and executed.

Example 11.35

graphics/11prfig01.gif

EXPLANATION

  1. The FCEDIT variable can be assigned the pathname for any of the UNIX text editors you have on your system, such as vi, emacs, etc. If not set, the vi editor is the default.

  2. The pwd command is typed at the command line. It will be placed in the history file.

  3. The fc command caused the editor (set in FCEDIT) to be invoked with the last command typed in the editor window. After the user writes and quits the editor, any commands typed there will be executed.

  4. The history command lists recently typed commands.

  5. The fc command is used to start up the editor with the last three commands from the history file in the editor's buffer.

11.2.4 Aliases

An alias is a bash user-defined abbreviation for a command. Aliases are useful if a command has a number of options and arguments or the syntax is difficult to remember. Aliases set at the command line are not inherited by subshells. Aliases are normally set in the .bashrc file. Because the .bashrc is executed when a new shell is started, any aliases set there will be reset for the new shell. Aliases may also be passed into shell scripts but will cause potential portability problems unless they are set directly within the script.

Listing Aliases. The alias built-in command lists all set aliases. The alias is printed first, followed by the real command or commands it represents.

Example 11.36
$ alias alias co='compress' alias cp='cp -i' alias mroe='more' alias mv='mv -i' alias ls='ls --colorztty' alias uc='uncompress' 

EXPLANATION

The alias command lists the alias (nickname) for the command and the real command the alias represents after the = sign.

Creating Aliases. The alias command is used to create an alias. The first argument is the name of the alias, the nickname for the command. The rest of the line consists of the command or commands that will be executed when the alias is executed. Bash aliases cannot take arguments (see "Defining Functions" on page 693). Multiple commands are separated by a semicolon, and commands containing spaces and metacharacters are surrounded by single quotes.

Example 11.37
1   $ alias m=more 2   $ alias mroe=more 3   $ alias lF='ls -alF' 4   $ alias r='fc -s' 

EXPLANATION

  1. The nickname for the more command is set to m.

  2. The alias for the more command is set to mroe. This is handy if you can't spell.

  3. The alias definition is enclosed in quotes because of the whitespace. The alias lF is a nickname for the command ls -alF.

  4. The alias r will be used instead of fc -s to recall commands from the history list by a specified pattern; e.g., r vi will reexecute the last command in the history list containing the pattern vi.

Deleting Aliases. The unalias command is used to delete an alias. To temporarily turn off an alias, precede the alias name by a backslash.

Example 11.38
1   $ unalias mroe 2   $ \ls 

EXPLANATION

  1. The unalias command deletes the alias mroe from the list of defined aliases.

  2. The alias ls is temporarily turned off for this execution of the command only.

11.2.5 Manipulating the Directory Stack

If you find that as you work, you cd up and down the directory tree into many of the same directories, you can make it easy to access those directories by pushing them onto a directory stack and manipulating the stack. The pushd built-in command pushes directories onto a stack and the popd command removes them. (See Example 11.39.) The stack is a list of directories with the directory at the left being the most recent directory pushed onto the stack. The directories can be listed with the built-in dirs command.

The dirs Built-In Command. The built-in command dirs, with a -l option, displays the directory stack with each of its directories in full pathname format; without an option, dirs uses a tilde to denote the home directory. With a +n option, dirs displays the nth directory entry counting from the left in the directory list, starting at 0. With -n option, it does the same thing, but starts at the right-hand side of the directory list with 0.

The pushd and popd Commands. The pushd command, with a directory as an argument, causes the new directory to be added to the directory stack and, at the same time, changes to that directory. If the argument is a +n where n is a number, pushd rotates the stack so that the nth directory from the stack, starting at the left-hand side, is pushed onto the top of the stack. With a -n option, it does the same thing but starts at the right-hand side. Without arguments, pushd exchanges the top two elements of the directory stack, making it easy to switch back and forth between directories.

The popd command removes a directory from the top of the stack, and changes to that directory. With +n, where n is a number, popd removes the nth entry, starting at the left of the list shown by dirs.

Example 11.39
1   $ pwd     /home/ellie     $ pushd ..     /home ~     $ pwd     /home 2   $ pushd       # Swap the two top directories on the stack     ~ /home     $ pwd     /home/ellie 3   $ pushd perlclass     ~/perlclass  ~  /home 4   $ dirs     ~/perlclass ~ /home 5   $ dirs -l     /home/ellie/perlclass /home/ellie  /home 6   $ popd     ~/home     $ pwd     /home/ellie 7   $ popd     /home     $ pwd     /home 8   $ popd     bash: popd: Directory stack empty. 

EXPLANATION

  1. First the pwd command displays the present working directory, /home/ellie. Next the pushd command with .. as its argument, pushes the parent directory (..) onto the directory stack. The output of pushd indicates that /home is at the top of the directory stack (starting at the left-hand side of the displayed list) and the user's home directory, represented by the tilde character (~) is at the bottom of the stack. pushd also changes the directory to the one that was pushed onto the stack; i.e., .. which translates to /home. The new directory is displayed with the second pwd command.

  2. Pushd, without arguments, exchanges the two top directory entries on the stack and changes to the swapped directory; in this example, the directory is switched back to the user's home directory, /home/ellie.

  3. The pushd command will push its argument, ~/perlclass, onto the stack, and change to that directory.

  4. The built-in dirs command displays the directory stack, with the top level starting at left-hand side of the listing. The tilde expands to the user's home directory.

  5. With the -l option, dirs list displays the directory stack with full pathnames instead of using tilde expansion.

  6. The popd command removes a directory from the top of the stack, and changes to that directory.

  7. The popd command removes another directory from the top of the stack, and changes to that directory.

  8. The popd command cannot remove any more directory entries because the stack is empty, and issues an error message saying so.

11.2.6 Metacharacters (Wildcards)

Metacharacters are special characters used to represent something other than themselves. Shell metacharacters are called wildcards. Table 11.10 lists metacharacters and what they do.

Table 11.10. Metacharacters
Metacharacter Meaning
\ Literally interprets the following character.
& Processes in the background.
; Separates commands.
$ Substitutes variables.
? Matches for a single character.
[abc] Matches for one character from a set of characters; e.g., a, b, or c.
[!abc] Matches for one character not from the set of characters; e.g., not a, b, or c.
* Matches for zero or more characters.
(cmds) Executes commands in a subshell.
{cmds} Executes commands in current shell.

11.2.7 Filename Substitution (Globbing)

When evaluating the command line, the shell uses metacharacters to abbreviate filenames or pathnames that match a certain set of characters. The filename substitution metacharacters listed in Table 11.11 are expanded into an alphabetically listed set of filenames. The process of expanding the metacharacter into filenames is also called filename substitution, or globbing. If a metacharacter is used and there is no filename that matches it, the shell treats the metacharacter as a literal character.

Table 11.11. Shell Metacharacters and Filename Substitution
Metacharacter Meaning
* Matches zero or more characters.
? Matches exactly one character.
[abc] Matches one character in the set a, b, or c.
[!abc] Matches one character not in the set, not a, b, or c.
{a,ile,ax} Matches for a character or set of characters.
[! a z] Matches one character not in the range from a to z.
\ Escapes or disables the metacharacter.

The Asterisk. The asterisk is a wildcard that matches for zero or more of any characters in a filename.

Example 11.40
1   $ ls  *     abc abc1 abc122 abc123 abc2 file1 file1.bak file2 file2.bak none     nonsense nobody nothing nowhere one 2   $ ls  *.bak     file1.bak file2.bak 3   $ echo a*     ab abc1 abc122 abc123 abc2 

EXPLANATION

  1. The asterisk expands to all of the files in the present working directory. All of the files are passed as arguments to ls and displayed.

  2. All files starting with zero or more characters and ending with .bak are matched and listed.

  3. All files starting with a, followed by zero or more characters, are matched and passed as arguments to the echo command.

The Question Mark. The question mark represents a single character in a filename. When a filename contains one or more question marks, the shell performs filename substitution by replacing the question mark with the character it matches in the filename.

Example 11.41
1   $ ls     abc  abc122  abc2  file1.bak  file2.bak  nonsense  nothing  one     abc1  abc123  file1  file2  none  noone  nowhere 2   $ ls a?c?     abc1 abc2 3   $ ls ??     ls: ??: No such file or directory 4   $ echo  abc???     abc122 abc123 5   $ echo ??     ?? 

EXPLANATION

  1. The files in the current directory are listed.

  2. Filenames starting with a, followed by a single character, followed by c and a single character, are matched and listed.

  3. Filenames containing exactly two characters are listed, if found. Because there are not any two-character files, the question marks are treated as a literal filename. Such a file is not found, and the error message is printed.

  4. Filenames starting with abc and followed by exactly three characters are expanded and displayed by the echo command.

  5. There are no files in the directory that contain exactly two characters. The shell treats the question mark as a literal question mark if it cannot find a match.

The Square Brackets. The brackets are used to match filenames containing one character in a set or range of characters.

Example 11.42
1   $ ls     abc abc122 abc2 file1.bak file2.bak nonsense nothing     one abc1 abc123 file1 file2 none noone nowhere 2   $ ls abc[123]     abc1  abc2 3   $ ls abc[1 3]     abc1  abc2 4   $ ls [a z][a z][a z]     abc one 5   $ ls [!f z]???     abc1  abc2 6   $ ls abc12[23]     abc122 abc123 

EXPLANATION

  1. All of the files in the present working directory are listed.

  2. All filenames containing four characters are matched and listed if the filename starts with abc, followed by 1, 2, or 3. Only one character from the set in the brackets is matched.

  3. All filenames containing four characters are matched and listed, if the filename starts with abc and is followed by a number in the range from 1 to 3.

  4. All filenames containing three characters are matched and listed, if the filename contains exactly three lowercase alphabetic characters.

  5. All filenames containing four characters are listed if the first character is not a letter between f and z ([!f z], followed by three of any characters, where ? represents a single character.

  6. Files are listed if the filenames contain abc12 followed by 2 or 3.

Brace Expansion. The curly braces match for any of a list of comma-separated strings. Normally the strings are filenames. Any characters prepended to the opening curly brace are called the preamble, and any characters appended to the closing curly brace are called the postamble. Both the preamble and postamble are optional. There can be no unquoted whitespace within the braces.

Example 11.43
1   $ ls     a.c b.c abc ab3 ab4 ab5 file1 file2 file3 file4 file5 foo     faa fumble 2   $ ls f{oo,aa,umble}     foo faa fumble 3   $ ls a{.c,c,b[3-5]}     a.c ab3 ab4 ab5 4   $ mkdir /usr/local/src/bash/{old,new,dist,bugs} 5   $ chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}} 6   $ echo fo{o, um}*     fo{o, um}* 7   $ echo {mam,pap,ba}a     mama papa baa 8   $ echo post{script,office,ure}     postscript postoffice posture 

EXPLANATION

  1. All the files in the current directory are listed.

  2. Files starting with f and followed by the strings oo, aa, or umble are listed. Spaces inside the curly braces will cause the error message Missing }.

  3. Files starting with a followed by .c, c, or b3, b4, or b5 are listed. (The square brackets can be used inside the curly braces.)

  4. Four new directories will be made in /usr/local/src/bash: old, new, dist, and bugs.

  5. Root ownership will be given to files, ex and edit, in directory /usr /ucb and to files named ex followed by one character, a period, and at least one more character, and a file called how_ex in directory /usr/lib.

  6. Brace expansion will not occur if there are any unquoted spaces within the braces.

  7. Brace expansion does not necessarily always cause expansion of filenames. In this example the postamble a is added to each of the strings within the curly braces and echoed back after the expansion.

  8. The preamble is the string post, followed by a comma-separated list enclosed within braces. Brace expansion is performed and the resulting strings are displayed.

Escaping Metacharacters. To use a metacharacter as a literal character, use the backslash to prevent the metacharacter from being interpreted.

Example 11.44
1   $ ls     abc file1 youx 2   $ echo How are you?     How are youx 3   $ echo How are you\?     How are you? 4   $ echo  When does this line \     > ever end\?     When does this line ever end? 

EXPLANATION

  1. The files in the present working directory are listed. (Note the file youx.)

  2. The shell will perform filename expansion on the ?. Any files in the current directory starting with y-o-u and followed by exactly one character are matched and substituted in the string. The filename youx will be substituted in the string to read How are youx (probably not what you wanted to happen).

  3. By preceding the question mark with a backslash, it is escaped, meaning that the shell will not try to interpret it as a wildcard.

  4. The newline is escaped by preceding it with a backslash. The secondary prompt is displayed until the string is terminated with a newline. The question mark (?) is escaped to protect it from filename expansion.

Tilde and Hyphen Expansion. The tilde character was adopted by the bash shell (from the C shell) for pathname expansion. The tilde by itself evaluates to the full pathname of the user's home directory.[8] When the tilde is appended with a username, it expands to the full pathname of that user.

When the plus sign follows the tilde, the value of the PWD (present working directory) replaces the tilde. The tilde followed by the hyphen character is replaced with the previous working directory; OLDPWD also refers to the previous working directory.

Example 11.45
1   $ echo ~     /home/jody/ellie 2   $ echo ~joe     /home/joe 3   $ echo ~+     /home/jody/ellie/perl 4   $ echo ~-     /home/jody/ellie/prac 5   $ echo $OLDPWD    /home/jody/ellie/prac 6   $ cd -     /home/jody/ellie/prac 

EXPLANATION

  1. The tilde evaluates to the full pathname of the user's home directory.

  2. The tilde preceding the username evaluates to the full pathname of joe's home directory.

  3. The ~+ notation evaluates to the full pathname of the working directory.

  4. The ~- notation evaluates to the previous working directory.

  5. The OLDPWD variable contains the previous working directory.

  6. The hyphen refers to the previous working directory; cd to go to the previous working directory and display the directory.

Controlling Wildcards (Globbing). If the bash noglob variable is set or if the set command is given a -f option, filename substitution, called globbing, is turned off, meaning that all metacharacters represent themselves; they are not used as wildcards. This can be useful when searching for patterns containing metacharacters in programs like grep, sed, or awk. If globbing is not set, all metacharacters must be escaped with a backslash to turn off wildcard interpretation.

The built-in shopt command (bash versions 2.x) also supports options for controlling globbing.

Example 11.46
1   $ set noglob or set -f 2   $ print * ?? [] ~ $LOGNAME     * ?? [] /home/jody/ellie ellie 3   $ unset noglob or set +f 4   $ shopt -s dotglob   # Only available in bash versions 2.x 5   $ echo *bash*     .bash_history .bash_logout .bash_profile .bashrc bashnote     bashtest 

EXPLANATION

  1. The -f option is given as an argument to the set command. It turns off the special meaning of wildcards used for filename expansion.

  2. The filename expansion metacharacters are displayed as themselves without any interpretation. Note that the tilde and the dollar sign are still expanded, because they are not used for filename expansion.

  3. If either noglob is unset or the +f option is set, filename metacharacters will be expanded.

  4. The shopt built-in allows you to set options for the shell. The dotglob option allows filenames to be matched with globbing metacharacters, even if they start with a dot. Normally the files starting with a dot are invisible and not recognized when performing filename expansion.

  5. Because the dotglob option was set in line 4, when the wildcard * is used for filename expansion, the filenames starting with a dot are also expanded if the filename contains the pattern bash.

Extended Filename Globbing (bash 2.x). Derived from Korn shell pattern matching, bash 2.x has included this extended functionality, allowing regular expression-type syntax. The regular expression operators are not recognized unless the extglob option to the shopt command is turned on:

shopt -s extglob 
Table 11.12. Extended Pattern Matching
Regular Expression Meaning
abc?(2|9)1 ? matches zero or one occurrences of any pattern in the parentheses. The vertical bar represents an or condition; e.g., either 2 or 9. Matches abc21, abc91, or abc1.
abc*([0 9]) * matches zero or more occurrences of any pattern in the parentheses. Matches abc followed by zero or more digits; e.g., abc, abc1234, abc3, abc2, etc.
abc+([0 9]) + matches one or more occurrences of any pattern in the parentheses. Matches abc followed by one or more digits; e.g., abc3, abc123, etc.
no@(one|ne) @ matches exactly one occurrence of any pattern in the parentheses. Matches noone or none.
no!(thing|where) ! matches all strings except those matched by any of the patterns in the parentheses. Matches no, nobody, or noone, but not nothing or nowhere.
Example 11.47
1   $ shopt -s extglob 2   $ ls     abc      abc122    f1    f3     nonsense   nothing   one     abc1     abc2      f2    none   noone      nowhere 3   $ ls abc?(1|2)     abc      abc1      abc2 4   $ ls abc*([1-5])     abc      abc1      abc122     abc2 5   $ ls abc+([0-5])     abc1     abc122    abc2 6   $ ls no@(thing|ne)     none     nothing 7   $ ls no!(thing)     none     nonsense   noone     nowhere 

EXPLANATION

  1. The shopt built-in is used to set the extglob (extended globbing) option, allowing bash to recognize extended pattern matching characters.

  2. All the files in the present working directory are listed.

  3. Matches filenames starting with abc and followed by zero characters or one of either of the patterns in parentheses. Matches abc, abc1, or abc2.

  4. Matches filenames starting with abc and followed by zero or more numbers between 1 and 5. Matches abc, abc1, abc122, abc123, and abc2.

  5. Matches filenames starting with abc and followed by one or more numbers between 0 and 5. Matches abc1, abc122, abc123, and abc2.

  6. Matches filenames starting with no and followed by exactly thing or ne. Matches nothing or none.

  7. Matches filenames starting with no and followed by anything except thing. Matches none, nonsense, noone, and nowhere. The ! means not.

11.3 Variables

Types of Variables. There are two types of variables: local and environment. Local variables are known only to the shell in which they were created. Environment variables are available to any child processes spawned from the shell from which they were created. Some variables are created by the user and others are special shell variables.

Naming Conventions. Variable names must begin with an alphabetic or underscore character. The remaining characters can be alphabetic, decimal digits (0 to 9), or an underscore character. Any other characters mark the termination of the variable name. Names are case-sensitive. When assigning a value to a variable, do not include any whitespace surrounding the equal sign. To set the variable to null, follow the equal sign with a newline. The simplest format for creating a local variable is to assign a value to a variable in the following format.

FORMAT

variable=value 
Example 11.48
name=Tommy 

The declare Built-In. There are two built-in commands, declare and typeset, used to create variables, with options to control the way the variable is set. The typeset command (from Korn shell) is exactly the same as the declare command (bash). The bash documentation says, "The typeset command is supplied for compatibility with the Korn shell; however, it has been deprecated in favor of the declare built-in command."[9] So from this point on we'll use the declare built-in (even though we could just as easily have chosen to use typeset).

Without arguments, declare lists all set variables. Normally read-only variables cannot be reassigned or unset. If read-only variables are created with declare, they cannot be unset, but they can be reassigned. Integer-type variables can also be assigned with declare.

FORMAT

declare variable=value 
Example 11.49
declare name=Tommy 
Table 11.13. declare Options
Option Meaning
-f Lists functions names and definitions.
-r Makes variables read-only.
-x Exports variable names to subshells.
-i Makes variables integer types.
-a[a] Treats variable as an array; i.e., assigns elements.
-F[a] Lists just function names.

[a] a and -F are implemented only on versions of bash 2.x.

11.3.1 Local Variables and Scope

The scope of a variable refers to where the variable is visible within a program. For the shell, the scope of local variables is confined to the shell in which the variable is created.

When assigning a value, there can be no whitespace surrounding the equal sign. To set the variable to null, the equal sign is followed by a newline.[10]

A dollar sign is used in front of a variable to extract the value stored there.

The local function can be used to create local variables, but this is only used within functions. (See "Defining Functions" on page 693.)

Setting Local Variables. Local variables can be set by simply assigning a value to a variable name, or by using the declare built-in function as shown in Example 11.50.

Example 11.50
1   $ round=world or declare round=world     $ echo $round     world 2   $ name="Peter Piper"     $ echo $name     Peter Piper 3   $ x=     $ echo $x 4   $ file.bak="$HOME/junk"     bash: file.bak=/home/jody/ellie/junk: not found 

EXPLANATION

  1. The local variable round is assigned the value world. When the shell encounters the dollar sign preceding a variable name, it performs variable substitution. The value of the variable is displayed. (Don't confuse the prompt ($) with the $ used to perform variable substitution.)

  2. The local variable name is assigned the value "Peter Piper". The quotes are needed to hide the whitespace so that the shell will not split the string into separate words when it parses the command line. The value of the variable is displayed.

  3. The local variable x is not assigned a value. It will be assigned null. The null value, an empty string, is displayed.

  4. The period in the variable name is illegal. The only characters allowed in a variable name are numbers, letters, and the underscore. The shell tries to execute the string as a command.

Example 11.51
1   $ echo $$     1313 2   $ round=world     $ echo $round     world 3   $ bash                # Start a subshell 4   $ echo $$     1326 5   $ echo $round 6   $ exit                # Exits this shell, returns to parent shell 7   $ echo $$     1313 8   $ echo $round     world 

EXPLANATION

  1. The value of the double dollar sign variable evaluates to the PID of the current shell. The PID of this shell is 1313.

  2. The local variable round is assigned the string value world, and the value of the variable is displayed.

  3. A new bash shell is started. This is called a subshell, or child shell.

  4. The PID of this shell is 1326. The parent shell's PID is 1313.

  5. The local variable round is not defined in this shell. A blank line is printed.

  6. The exit command terminates this shell and returns to the parent shell. (Control-D will also exit this shell.)

  7. The parent shell returns. Its PID is displayed.

  8. The value of the variable round is displayed. It is local to this shell.

Setting Read-Only Variables. A read-only variable is a special variable that cannot be redefined or unset. If, however, the declare function is used, a read-only variable can be redefined, but not unset.

Example 11.52
1   $ name=Tom 2   $ readonly name     $ echo $name     Tom 3   $ unset name     bash: unset: name: cannot unset: readonly variable 4   $ name=Joe     bash: name: readonly variable 5   $ declare -r city='Santa Clara' 6   $ unset city     bash: unset: city: cannot unset: readonly variable 7   $ declare city='San Francisco'    # What happened here?     $ echo $city     San Francisco 

EXPLANATION

  1. The local variable name is assigned the value Tom.

  2. The variable is made read-only.

  3. A read-only variable cannot be unset.

  4. A read-only variable cannot be redefined.

  5. The declare built-in command assigns a read-only variable, city, the value Santa Clara. Quotes are necessary when assigning a string containing whitespace.

  6. Since it is read-only, the variable cannot be unset.

  7. When a read-only variable is created with the declare command, it cannot be unset, but it can be reassigned.

11.3.2 Environment Variables

Environment variables are available to the shell in which they are created and any subshells or processes spawned from that shell. They are often called global variables to differentiate them from local variables. By convention, environment variables are capitalized. Environment variables are variables that have been exported with the export built-in command.

The shell in which a variable is created is called the parent shell. If a new shell is started from the parent shell, it is called the child shell. Environment variables are passed to any child process started from the shell where the environment variables were created. They are passed from parent to child to grandchild, etc., but not the other direction; i.e., a child process can create an environment variable, but cannot pass it back to its parent, only to its children.[11] Some of the environment variables, such as HOME, LOGNAME, PATH, and SHELL, are set before you log on by the /bin/login program. Normally, environment variables are defined and stored in the .bash_profile file in the user's home directory. See Table 11.15 for a list of environment variables.

Setting Environment Variables. To set environment variables, the export command is used either after assigning a value or when the variable is set. The declare built-in, given the -x option, will do the same. (Do not use the $ on a variable when exporting it.)

FORMAT

export variable=value variable=value; export variable declare -x variable=value 
Example 11.53
export NAME=john PS1= '\d:\W:$USER> ' ; export PS1 declare -x TERM=sun 
Table 11.14. The export Command and Its Options
Option Value
- - Marks the end of option processing; the remaining parameters are arguments.
-f Name-value pairs are treated as functions, not variables.
-n Converts a global (exported) variable to a local variable. The variable will not be exported to child processes.
-p Displays all the global variables.
Example 11.54
1   $ export TERM=sun    # or declare -x TERM=sun 2   $ NAME="John Smith"     $ export NAME     $ echo $NAME     John Smith 3   $ echo $$     319             # pid number for parent shell 4   $ bash          # Start a subshell 5   $ echo $$     340             # pid number for new shell 6   $ echo $NAME     John Smith 7   $ declare -x NAME="April Jenner"     $ echo $NAME     April Jenner 8   $ exit                     # Exit the subshell and go back to parent shell 9   $ echo $$     319             # pid number for parent shell 10  $ echo $NAME     John Smith 

EXPLANATION

  1. The TERM variable is assigned sun. The variable is exported at the same time. Now, processes started from this shell will inherit the variable. You can use declare -x to do the same thing.

  2. The variable NAME is defined and exported to make it available to subshells started from the shell.

  3. The value of this shell's PID is printed.

  4. A new bash shell is started. The new shell is called the child. The original shell is its parent.

  5. The PID of the new bash shell is stored in the $$ variable and its value is echoed.

  6. The variable, set in the parent shell, was exported to this new shell and is displayed.

  7. The built-in declare function is another way to set a variable. With the -x switch, declare marks the variable for export. The variable is reset to April Jenner. It is exported to all subshells, but will not affect the parent shell. Exported values are not propagated upward to the parent shell.

  8. This bash child shell is exited.

  9. The PID of the parent is displayed again.

  10. The variable NAME contains its original value. Variables retain their values when exported from parent to child shell. The child cannot change the value of a variable for its parent.

 

Table 11.15. Bash Environment Variables
Variable Name Meaning
_ (underscore) The last argument to the previous command.
BASH Expands to the full pathname used to invoke this instance of bash.
BASH_ENV Same as ENV but set only in bash versions 2.0 or above.[a]
BASH_VERSINFO Version information about this version of bash if the version is 2.0 or above.[a]
BASH_VERSION Expands to the version number of this instance of bash.
CDPATH The search path for the cd command. This is a colon-separated list of directories in which the shell looks for destination directories specified by the cd command. A sample value is .:~:/usr.
COLUMNS If set, defines the width of the edit window for shell edit modes and the select command.
DIRSTACK The current contents of the directory stack if the bash version is 2.0 or above.[a]
EDITOR Pathname for a built-in editor: emacs, gmacs, or vi.
ENV The environment file that is executed every time a new bash shell is started, including a script. Normally the filename assigned to this variable is .bashrc. The value of ENV is subjected to parameter expansion, command substitution, and arithmetic expansion before being interpreted as a pathname.
EUID Expands to the effective user ID of the current user, initialized at shell startup.
FCEDIT Default editor name for the fc command.
FIGNORE A colon-separated list of suffixes to ignore when performing filename completion. A filename whose suffix matches one of the entries in FIGNORE is excluded from the list of matched filenames. A sample value is .o:~.
FORMAT Used to format the output of the time reserved word on a command pipeline.
GLOBIGNORE A list of files that will be ignored during filename expansion (called globbing).[a]
GROUPS An array of groups to which the current user belongs.[a]
HISTCMD The history number, or index in the history list, of the current command. If HISTCMD is unset, it loses its special properties, even if it is subsequently reset.
HISTCONTROL If set to a value of ignorespace, lines that begin with a space character are not entered on the history list. If set to a value of ignoredups, lines matching the last history line are not entered. A value of ignoreboth combines the two options. If unset, or if set to any other value than those above, all lines read by the parser are saved on the history list.
HISTFILE Specifies file in which to store command history. The default value is ~/.bash_history. If unset, the command history is not saved when an interactive shell exits.
HISTFILESIZE The maximum number of lines contained in the history file. When this variable is assigned a value, the history file is truncated, if necessary, to contain no more than that number of lines. The default value is 500.
HISTSIZE The number of commands to remember in the command history. The default value is 500.
HOME Home directory; used by cd when no directory is specified.
HOSTFILE Contains the name of a file in the same format as in /etc/hosts that should be read when the shell needs to complete a hostname. The file may be changed interactively; the next time hostname completion is attempted, bash adds the contents of the new file to the already existing database.
HOSTTYPE Automatically set to the type of machine on which bash is executing. The default is system-dependent.
IFS Internal field separators, normally SPACE, TAB, and NEWLINE, used for field splitting of words resulting from command substitution, lists in loop constructs, and reading input.
IGNOREEOF Controls the action of the shell on receipt of an EOF character as the sole input. If set, the value is the number of consecutive EOF characters typed as the first characters on an input line before bash exits. If the variable exists but does not have a numeric value, or has no value, the default value is 10. If it does not exist, EOF signifies the end of input to the shell. This is only in effect for interactive shells.
INPUTRC The filename for the readline startup file, overriding the default of ~./inputrc.
LANG Used to determine the locale category for any category not specifically selected with a variable starting with LC_.[a]
LC_ALL Overrides the value of LANG and any other LC_ variable.[a]
LC_COLLATE Determines the collation order used when sorting the results of pathname expansion and the behavior of range expressions, equivalence classes, and collating sequences when matching pathnames and patterns.[a]
LC_MESSAGES Determines the locale used to translate double-quoted strings preceded by a $.[a]
LINENO Each time this parameter is referenced, the shell substitutes a decimal number representing the current sequential line number (starting with 1) within a script or function.
MACHTYPE Contains a string describing the system on which bash is executing.[a]
MAIL If this parameter is set to the name of a mail file and the MAILPATH parameter is not set, the shell informs the user of the arrival of mail in the specified file.
MAIL_WARNING If set, and a file that bash is checking for mail has been accessed since the last time it was checked, the message The mail in [filename where mail is stored] has been read is printed.
MAILCHECK This parameter specifies how often (in seconds) the shell will check for the arrival of mail in the files specified by the MAILPATH or MAIL parameters. The default value is 600 seconds (10 minutes). If set to zero, the shell will check before issuing each primary prompt.
MAILPATH A colon-separated list of filenames. If this parameter is set, the shell informs the user of the arrival of mail in any of the specified files. Each filename can be followed by a % and a message that will be printed when the modification time changes. The default message is You have mail.
OLDPWD Last working directory.
OPTARG The value of the last option argument processed by the getopts built-in command.
OPTERR If set to 1, displays error messages from the getopts built-in.
OPTIND The index of the next argument to be processed by the getopts built-in command.
OSTYPE Automatically set to a string that describes the operating system on which bash is executing. The default is system-dependent.
PATH The search path for commands. It is a colon-separated list of directories in which the shell looks for commands. The default path is system-dependent, and is set by the administrator who installs bash. A common value is /usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:.
PIPESTATUS An array containing a list of exit status values from processes in the most recently executed foreground jobs in a pipeline.
PPID Process ID of the parent process.
PROMPT_COMMAND The command assigned to this variable is executed before the primary prompt is displayed.
PS1 Primary prompt string, by default $.
PS2 Secondary prompt string, by default >.
PS3 Selection prompt string used with the select command, by default #?.
PS4 Debug prompt string used when tracing is turned on, by default +. Tracing can be turned on with set -x.
PWD Present working directory; set by cd.
RANDOM Each time this parameter is referenced, a random integer is generated. The sequence of random numbers may be initialized by assigning a value to RANDOM. If RANDOM is unset, it loses its special properties, even if it is subsequently reset.
REPLY Set when read is not supplied arguments.
SECONDS Each time SECONDS is referenced, the number of seconds since shell invocation is returned. If a value is assigned to SECONDS, the value returned upon subsequent references is the number of seconds since the assignment plus the value assigned. If SECONDS is unset, it loses its special properties, even if it is subsequently reset.
SHELL When the shell is invoked, it scans the environment for this name. The shell gives default values to PATH, PS1, PS2, MAILCHECK, and IFS. HOME and MAIL are set by login(1).
SHELLOPTS Contains a list of enabled shell options, such as braceexpand, hashall, monitor, etc.
SHLVL Incremented by one each time an instance of bash is started.
TMOUT Specifies number of seconds to wait for input before exiting.
UID Expands to the user ID of the current user, initialized at shell startup.

[a] Not available in bash versions prior to 2.x.

Unsetting Variables. Both local and environment variables can be unset by using the unset command, unless the variables are set as read-only.

Example 11.55
unset name; unset TERM 

EXPLANATION

The unset command removes the variable from the shell's memory.

Printing the Values of Variables: The echo Command. The built-in echo command prints its arguments to standard output. Echo, with the -e option, allows the use of numerous escape sequences that control the appearance of the output. Table 11.16 lists the echo options and escape sequences.

Table 11.16. echo Options and Escape Sequences
Option Meaning
-e Allows interpretation of the escape sequences shown below.
-n Suppresses newline at the end of a line of output.
-E[a] Disables the interpretation of these escape characters, even on systems where they are interpreted by default (bash 2.x).
Escape Sequence
\a[a] Alert (bell).
\b Backspace.
\c Prints the line without a newline.
\f Form feed.
\n Newline.
\r Return.
\t Tab.
\v Vertical tab.
\\ Backslash.
\nnn The character whose ASCII code is nnn (octal).

[a] Not available in bash versions prior to 2.x.

When using the escape sequences, don't forget to use the -e switch!

Example 11.56
1   $ echo The username is $LOGNAME.     The username is ellie. 2   $ echo -e "\t\tHello there\c"                 Hello there$ 3   $ echo -n "Hello there"     Hello there$ 

EXPLANATION

  1. The echo command prints its arguments to the screen. Variable substitution is performed by the shell before the echo command is executed.

  2. The echo command, with the -e option, supports escape sequences similar to those of the C programming language. The $ is the shell prompt.

  3. When the -n option is on, the line is printed without the newline. The escape sequences are not supported by this version of echo.

The printf Command. The GNU version of printf[12] can be used to format printed output. It prints the formatted string in the same way as the C printf function. The format consists of a string that may contain formatting instructions to describe how the printed output will look. The formatting instructions are designated with a % followed by specifiers (diouxXfeEgGcs) where %f would represent a floating point number and %d would represent a whole (decimal) number.

To see a complete listing of printf specifiers and how to use them, type at the command line prompt: printf - -help. To see what version of printf you are using, type: printf - -version. If you are using bash 2.x, the built-in printf command uses the same format as the executable version in /usr/bin.

FORMAT

printf format [argument...] 
Example 11.57
printf "%10.2f%5d\n" 10.5  25 
Table 11.17. Format Specifiers for the printf Command
Format Specifier Value
\" Double quote.
\0NNN An octal character where NNN represents 0 to 3 digits.
\\ Backslash.
\a Alert or beep.
\b Backspace.
\c Produce no further output.
\f Form feed.
\n Newline.
\r Return.
\t Horizontal tab.
\v Vertical tab.
\xNNN Hexadecimal character, where NNN is 1 to 3 digits.
%% A single %.
%b Argument as a string with \ escapes interpreted.
Example 11.58
1   $ printf --version     printf (GNU sh-utils) 1.16 2   $ type printf     printf is a shell builtin 3   $ printf "The number is %.2f\n" 100     The number is 100.00 4   $ printf "%-20s%-15s%10.2f\n" "Jody" "Savage" 28     Jody                Savage              28.00 5   $ printf "|%-20s|%-15s|%10.2f|\n" "Jody" "Savage" 28     Jody                |Savage         |     28.00| 6   $ printf "%s's average was %.1f%%.\n" "Jody" $(( (80+70+90)/3 ))     Jody's average was 80.0%. 

EXPLANATION

  1. The GNU version of the printf command is printed.

  2. If using bash2.x, printf is a built-in command.

  3. The argument 100 is printed as a floating point number with only 2 places to the right of the decimal point as designated by the specification %.2f in the format string. Unlike C, there are no commas separating the arguments.

  4. The format string specifies that three conversions will take place: the first one is %-20s (a left-justified, 20-character string), next is %-15s (a left-justified, 15-character string, and last %10.2f (a right-justified, 10-character floating point number, one of whose characters is the period and the last two characters are the two numbers to the right of the decimal point). Each argument is formatted in the order of the corresponding % signs, so that string Jody corresponds to first %, string Savage corresponds to the second %, and the number 28 to the last % sign.

  5. This line is the same as line 4 except vertical bars have been added to demonstrate left- and right-justification of the strings.

  6. The printf command formats the string Jody and formats the result of the arithmetic expansion. (See "Arithmetic Expansion".) Two percent (%%) signs are needed to print one percent sign (%).

Variable Expansion Modifiers (Parameter Expansion). Variables can be tested and modified by using special modifiers. The modifier provides a shortcut conditional test to check if a variable has been set, and then assigns a value to the variable based on the outcome of the test. See Table 11.18 for a list of variable modifiers.

Table 11.18. Variable Modifiers
Modifier Value
${variable:-word} If variable is set and is non-null, substitute its value; otherwise, substitute word.
${variable:=word} If variable is set or is non-null, substitute its value; otherwise, set it to word. The value of variable is substituted permanently. Positional parameters may not be assigned in this way.
${variable:+word} If variable is set and is non-null, substitute word; otherwise, substitute nothing.
${variable:?word} If variable is set and is non-null, substitute its value; otherwise, print word and exit from the shell. If word is omitted, the message parameter null or not set is printed.
${variable:offset} Gets the substring of the value in variable starting at offset, where offset starts at 0 to the end of the string.[a]
${variable:offset:length} Gets the substring of the value in variable starting at offset, length characters over.

[a] Not available on bash versions prior to 2.0.

Using the colon with any of the modifiers (-, =, +, ?) checks whether the variable is not set or is null; without the colon, a variable set to null is considered to be set.

Example 11.59
(Substitute Temporary Default Values) 1  $ fruit=peach 2  $ echo ${fruit:-plum}    peach 3  $ echo ${newfruit:-apple}    apple 4  $ echo $newfruit 5  $ echo $EDITOR       # More realistic example 6  $ echo ${EDITOR:-/bin/vi}    /bin/vi 7  $ echo $EDITOR 8  $ name=    $ echo ${name-Joe} 9  $ echo ${name:-Joe}    Joe 

EXPLANATION

  1. The variable fruit is assigned the value peach.

  2. The special modifier will check to see if the variable fruit has been set. If it has, the value is printed; if not, plum is substituted for fruit and its value is printed.

  3. The variable newfruit has not been set. The value apple will be temporarily substituted for newfruit.

  4. The setting was only temporary. The variable newfruit is not set.

  5. The environment variable EDITOR has not been set.

  6. The :- modifier substitutes EDITOR with /bin/vi.

  7. The EDITOR was never set. Nothing prints.

  8. The variable name is set to null. By not prefixing the modifier with a colon, the variable is considered to be set, even if to null, and the new value Joe is not assigned to name.

  9. The colon causes the modifier to check that a variable is either not set or is set to null. In either case, the value Joe will be substituted for name.

Example 11.60
(Substitute Permanent Default Values) 1  $ name= 2  $ echo  ${name:=Peter}    Peter 3  $ echo $name    Peter 4  $ echo ${EDITOR:=/bin/vi}    /bin/vi 5  $ echo $EDITOR    /bin/vi 

EXPLANATION

  1. The variable name is assigned the null value.

  2. The special modifier := will check to see if the variable name has been set. If it has been set, it will not be changed; if it is either null or not set, it will be assigned the value to the right of the equal sign. Peter is assigned to name since the variable is set to null. The setting is permanent.

  3. The variable name still contains the value Peter.

  4. The value of the variable EDITOR is set to /bin/vi.

  5. The value of the variable EDITOR is displayed.

Example 11.61
(Substitute Temporary Alternate Value) 1  $ foo=grapes 2  $ echo ${foo:+pears}    pears 3  $ echo $foo    grapes    $ 

EXPLANATION

  1. The variable foo has been assigned the value grapes.

  2. The special modifier :+ will check to see if the variable has been set. If it has been set, pears will temporarily be substituted for foo; if not, null is returned.

  3. The variable foo now has its original value.

Example 11.62
(Creating Error Messages Based On Default Values) 1  $ echo ${namex:?"namex is undefined"}    namex: namex is undefined 2  $ echo ${y?}    y: parameter null or not set 

EXPLANATION

  1. The :? modifier will check to see if the variable has been set. If not, the string to the right of the ? is printed to standard error, after the name of the variable. If in a script, the script exits.

  2. If a message is not provided after the ?, the shell sends a default message to standard error.

Example 11.63
(Creating Substring[a]) 1  $ var=notebook 2  $ echo ${var:0:4}    note 3  $ echo ${var:4:4}    book 4  $ echo ${var:0:2}    no 

[a] Not available in versions of bash prior to 2.x.

EXPLANATION

  1. The variable is assigned the value, notebook.

  2. The substring of var starts at offset 0, the n in notebook, and has a length of 4 characters, ending at the e.

  3. The substring of var starts at offset 4, the b in notebook, and has a length of 4 characters, ending at the k.

  4. The substring of var starts at offset 0, the n in notebook, and has a length of 2 characters, ending at the o.

Variable Expansion of Substrings. Pattern-matching arguments are used to strip off certain portions of a string from either the front or end of the string. The most common use for these operators is stripping off pathname elements from the head or tail of the path. See Table 11.19.

Table 11.19. Variable Expansion Substrings[a]
Expression Function
${variable%pattern} Matches the smallest trailing portion of the value of variable to pattern and removes it.
${variable%%pattern} Matches the largest trailing portion of the value of variable to pattern and removes it.
${variable#pattern} Matches the smallest leading portion of the value of variable to pattern and removes it.
${variable##pattern} Matches the largest leading portion of the value of variable to pattern and removes it.
${#variable} Substitutes the number of characters in the variable. If * or @, the length is the number of positional parameters.

[a] Not available on versions of bash prior to 2.x.

Example 11.64
1   $ pathname="/usr/bin/local/bin" 2   $ echo ${pathname%/bin*}     /usr/bin/local 

EXPLANATION

  1. The local variable pathname is assigned /usr/bin/local/bin.

  2. The % removes the smallest trailing portion of pathname containing the pattern /bin, followed by zero or more characters; that is, it strips off /bin.

Example 11.65
1   $ pathname="usr/bin/local/bin" 2   $ echo ${pathname%%/bin*}     /usr 

EXPLANATION

  1. The local variable pathname is assigned /usr/bin/local/bin.

  2. The %% removes the largest trailing portion of pathname containing the pattern /bin, followed by zero or more characters; that is, it strips off /bin/local/bin

Example 11.66
1   $ pathname=/home/lilliput/jake/.bashrc 2   $ echo ${pathname#/home}     /lilliput/jake/.bashrc 

EXPLANATION

  1. The local variable pathname is assigned /home/liliput/jake/.bashrc.

  2. The # removes the smallest leading portion of pathname containing the pattern /home; that is, /home is stripped from the beginning of the path variable.

Example 11.67
1   $ pathname=/home/liliput/jake/.bashrc 2   $ echo ${pathname##*/}     .bashrc 

EXPLANATION

  1. The local variable pathname is assigned /home/liliput/jake/.bashrc.

  2. The ## removes the largest leading portion of pathname containing zero or more characters up to and including the last slash; that is, it strips off /home/lilliput/jake from the path variable.

Example 11.68
1   $ name="Ebenezer Scrooge" 2   $ echo  ${#name}     16 

EXPLANATION

  1. The variable name is assigned the string Ebenezer Scrooge.

  2. The ${#variable} syntax displays the number of characters in the string assigned to the variable name. There are 16 characters in Ebenezer Scrooge.

Positional Parameters. Normally, the special built-in variables, often called positional parameters, are used in shell scripts when passing arguments from the command line, or used in functions to hold the value of arguments passed to the function. The variables are called positional parameters because they are referenced by numbers 1, 2, 3, and so on, representing their respective positions in the parameter list. See Table 11.20.

The name of the shell script is stored in the $0 variable. The positional parameters can be set, reset, and unset with the set command.

Table 11.20. Positional Parameters
Expression Function
$0 References the name of the current shell script.
$1 $9 Positional parameters 1 9.
${10} Positional parameter 10.
$# Evaluates to the number of positional parameters.
$* Evaluates to all the positional parameters.
$@ Same as $*, except when double quoted.
"$*" Evaluates to "$1 $2 $3", etc.
"$@" Evaluates to "$1" "$2" "$3", etc.
Example 11.69
1   $ set punky tommy bert jody     $ echo $*             # Prints all the positional parameters     punky tommy bert jody 2   $ echo $1             # Prints the first position     punky 3   $ echo $2 $3          # Prints the second and third position     tommy bert 4   $ echo $#             # Prints the total number of positional     4                     # parameters 5   $ set a b c d e f g h i j k l m     $ print $10           # Prints the first positional parameter     a0                    # followed by a 0.     $ echo ${10} ${11}    # Prints the 10th and 11th positions     j k 6   $ echo $#     13 7   $ echo $*     a b c d e f g h i j k l m 8   $ set file1 file2 file3     $ echo \$$#     $3 9   $ eval echo \$$#     file3 10  $ set --            # Unsets all positional parameters 

EXPLANATION

  1. The set command assigns values to positional parameters. The $* special variable contains all of the parameters set.

  2. The value of the first positional parameter, punky, is displayed.

  3. The value of the second and third parameters, tommy and bert, are displayed.

  4. The $# special variable contains the number of positional parameters currently set.

  5. The set command resets all of the positional parameters. The original parameter list is cleared. To print any positional parameters beyond 9, use the curly braces to keep the two digits together. Otherwise, the value of the first positional parameter is printed, followed by the number appended to it.

  6. The number of positional parameters is now 13.

  7. The values of all the positional parameters are printed.

  8. The dollar sign is escaped; $# is the number of arguments. The echo command displays $3, a literal dollar sign followed by the number of positional parameters.

  9. The eval command parses the command line a second time before executing the command. The first time parsed by the shell, the print would display $3; the second time, after eval, the print displays the value of $3, file3.

  10. The set command with the - - option clears or unsets all positional parameters.

Other Special Variables. The shell has special variables consisting of a single character.The dollar sign preceding the character allows you to access the value stored in the variable. See Table 11.21.

Table 11.21. Special Variables
Variable Meaning
$ The PID of the shell.
- The sh options currently set.
? The exit value of last executed command.
! The PID of the last job put in the background.
Example 11.70
1   $ echo The pid of this shell is $$     The pid of this shell is 4725 2   $ echo The options for this shell are $-     The options for this shell are imh 3   $ grep dodo /etc/passwd     $ echo $?     1 4   $ sleep 25&     4736     $ echo $!     4736 

EXPLANATION

  1. The $ variable holds the value of the PID for this process.

  2. The - variable lists all options for this interactive bash shell.

  3. The grep command searches for the string dodo in the /etc/passwd file. The ? variable holds the exit status of the last command executed. Since the value returned from grep is 1, grep is assumed to have failed in its search. An exit status of zero indicates a successful exit.

  4. The ! variable holds the PID number of the last command placed in the background. The & appended to the sleep command sends the command to the background.

11.3.3 Quoting

Quoting is used to protect special metacharacters from interpretation and prevent parameter expansion. There are three methods of quoting: the backslash, single quotes, and double quotes. The characters listed in Table 11.22 are special to the shell and must be quoted.

Table 11.22. Special Metacharacters Requiring Quotes
Metacharacter Meaning
; Command separator.
& Background processing.
( ) Command grouping; creates a subshell.
{ } Command grouping; does not create a subshell.
| Pipe.
< Input redirection.
> Output redirection.
newline Command termination.
space/tab Word delimiter.
$ Variable substitution character.
* [ ] ? Shell metacharacters for filename expansion.

Single and double quotes must be matched. Single quotes protect special metacharacters, such as $, *, ?, |, >, and <, from interpretation. Double quotes also protect special metacharacters from being interpreted, but allow variable and command substitution characters (the dollar sign and backquotes) to be processed. Single quotes will protect double quotes and double quotes will protect single quotes.

Unlike the Bourne shell, bash tries to let you know if you have mismatched quotes. If running interactively, a secondary prompt appears when quotes are not matched; if in a shell script, the file is scanned and if the quote is not matched, the shell will attempt to match it with the next available quote. If the shell cannot match it with the next available quote, the program aborts and the message bash:unexpected EOF while looking for '"' appears on the terminal. Quoting can be a real hassle for even the best of shell programmers! See Appendix C for shell quoting rules.

The Backslash. The backslash is used to quote (or escape) a single character from interpretation. The backslash is not interpreted if placed in single quotes. The backslash will protect the dollar sign ($), backquotes (' '), and the backslash from interpretation if enclosed in double quotes.

Example 11.71
1   $ echo Where are you going\?     Where are you going? 2   $ echo Start on this line and \     >  go to the next line.     Start on this line and go to the next line. 3   $ echo \\     \ 4   $ echo '\\'     \\ 5   $ echo '\$5.00'     \$5.00 6   $ echo  "\$5.00"     $5.00 7   $ echo 'Don\'t you need $5.00?'     >     >'     Don\t you need .00? 

EXPLANATION

  1. The backslash prevents the shell from performing filename substitution on the question mark.

  2. The backslash escapes the newline, allowing the next line to become part of this line.

  3. Because the backslash itself is a special character, it prevents the backslash following it from interpretation.

  4. The backslash is not interpreted when enclosed in single quotes.

  5. All characters in single quotes are treated literally. The backslash does not serve any purpose here.

  6. When enclosed in double quotes, the backslash prevents the dollar sign from being interpreted for variable substitution.

  7. The backslash is not interpreted when inside single quotes; therefore, the shell sees three single quotes (the one at the end of the string is not matched). A secondary prompt appears, waiting for a closing single quote. When the shell finally gets the closing quote, it strips out all of the quotes and passes the string on to the echo command. Because the first two quotes were matched, the rest of the string t you need $5.00? was not enclosed within any quotes. The shell tried to evaluate $5; it was empty and .00 printed.

Single Quotes. Single quotes must be matched. They protect all metacharacters from interpretation. To print a single quote, it must be enclosed in double quotes or escaped with a backslash.

Example 11.72
1   $ echo 'hi there     > how are you?     > When will this end?     > When the quote is matched     > oh'     hi there     how are you?     When will this end?     When the quote is matched     oh 2   $ echo Don\'t you need '$5.00?'     Don't you need $5.00? 3   $ echo 'Mother yelled, "Time to eat!"'     Mother yelled, "Time to eat!" 

EXPLANATION

  1. The single quote is not matched on the line. The Bourne shell produces a secondary prompt. It is waiting for the quote to be matched.

  2. The single quotes protect all metacharacters from interpretation. The apostrophe in Don't is escaped with a backslash (the backslash protects a single character, rather than a string). Otherwise, it would match the single quote before the $. Then the single quote at the end of the string would not have a mate. The $ and the ? are enclosed in a pair of single quotes, protecting them from shell interpretation; i.e., treating them as literals.

  3. The single quotes protect the double quotes in this string.

Double Quotes. Double quotes must be matched, will allow variable and command substitution, and protect any other special metacharacters from being interpreted by the shell.

Example 11.73
1   $ name=Jody 2   $ echo "Hi $name, I'm glad to meet you!"     Hi Jody, I'm glad to meet you! 3   $ echo "Hey $name, the time is $(date)"     Hey Jody, the time is Wed Jul 14 14:04:11 PST 2001 

EXPLANATION

  1. The variable name is assigned the string Jody.

  2. The double quotes surrounding the string will protect all special metacharacters from interpretation, with the exception of $ in $name. Variable substitution is performed within double quotes.

  3. Variable substitution and command substitution are both performed when enclosed within double quotes. The variable name is expanded, and the command in parentheses, date, is executed. (See "Command Substitution" below.)

11.3.4 Command Substitution

Command substitution is used when assigning the output of a command to a variable or when substituting the output of a command within a string. All shells use backquotes to perform command substitution.[13] Bash allows two forms: the older form, where the command(s) is placed within backquotes, and the new Korn-style form, where the command(s) is placed within a set of parentheses preceded by a dollar sign.

Bash performs the expansion by executing the command and returning the standard output of the command, with any trailing newlines deleted. When the old-style backquote form of substitution is used, the backslash retains its literal meaning except when followed by $, ', or \. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

Command substitutions may be nested. To nest when using the old form, the inner backquotes must be escaped with backslashes.

FORMAT

'UNIX command'    # Old method with backquotes $(UNIX command)   # New method 
Example 11.74
(The Old Way) 1   $ echo "The hour is 'date +%H'"     The hour is 09 2   $ name='awk -F: '{print $1}' database'     $ echo $name     Ebenezer Scrooge 3   $ ls 'ls /etc'     shutdown 4   $ set 'date' 5   $ echo $*     Wed Jul 14 09:35:21 PDT 2001 6   $ echo $2 $6     Jul 2001 7   $ echo 'basename \'pwd\''     ellie 

EXPLANATION

  1. The output of the date command is substituted into the string.

  2. The output of the awk command is assigned to the variable name and displayed.

  3. The output of the ls command, enclosed in backquotes, is a list of files from the /etc directory. The filenames will be arguments to the first ls command. All files with the same name in /etc in the current directory are listed. (The files that are not matches in this directory will cause an error message, such as ls: termcap: No such file or directory.)

  4. The set command assigns the output of the date command to positional parameters. Whitespace separates the list of words into its respective parameters.

  5. The $* variable holds all of the parameters. The output of the date command was stored in the $* variable. Each parameter is separated by whitespace.

  6. The second and sixth parameters are printed.

  7. To set the variable dirname to the name (only) of the present working directory, command substitution is nested. The pwd command is executed first, passing the full pathname of the present working directory as an argument to the UNIX command basename. The basename command strips off all but the last element of a pathname. When nesting commands within backquotes, the backquotes for the inner command must be escaped with a backslash.

The bash alternate for using backquotes in command substitution is presented below in Example 11.75.

Example 11.75
(The New Way) 1  $ d=$(date)    $ echo $d     Wed Jul 14 09:35:21 PDT 2001 2  $ lines = $(cat filex) 3  $ echo The time is $(date +%H)    The time is 09 4  $ machine=$(uname -n)    $ echo $machine    jody 5  $ pwd    /usr/local/bin    $ dirname="$(basename $(pwd)) "   # Nesting commands    $ echo $dirname    bin 6  $ echo $(cal)                           # Newlines are lost    July 2001 S M Tu W Th F S 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15    16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 7  $ echo "$(cal)"         July 2001     S  M  Tu  W  Th F  S                  1  2  3     4  5  6  7   8  9 10    11 12 13 14  15 16 17    18 19 20 21  22 23 24    25 26 27 28  29 30 31 

EXPLANATION

  1. The date command is enclosed within parentheses. The output of the command is substituted into the expression, then assigned to the variable d, and displayed.

  2. The output from the cat command is assigned to the variable lines.

  3. Again the date command is enclosed in parentheses. The output of date +%H, the current hour, is substituted for the expression and echoed to the screen.

  4. The variable machine is assigned the output of uname -n, the name of the host machine. The value of the machine variable is echoed to the screen.

  5. The output of the pwd command (present working directory) is /usr/local/bin.The variable dirname is assigned the output resulting from command substitution where the command substitutions are nested. $(pwd) is the first command substitution to be be performed. The output of the pwd command is substituted in the expression, then the basename program will use the results of that substitution, /usr/local/bin, as its argument, resulting in basename /usr/local/bin.

  6. The output of the cal (the current month) command is echoed. The trailing newlines are deleted when command substitution is performed.

  7. When you put the whole command substitution expression in double quotes, the trailing newlines are preserved, and calendar looks like it should.

11.3.5 Arithmetic Expansion

The shell performs arithmetic expansion by evaluating an arithmetic expression and substituting the result. The expression is treated as if it were in double quotes and the expressions may be nested. For a complete discussion of arithmetic operations, and arithmetic evaluations, see "The let Command" on page 732.

There are two formats for evaluating arithmetic expressions:

FORMAT

$[ expression ] $(( expression )) 
Example 11.76
echo $[ 5 + 4 - 2 ] 7 echo $[ 5 + 3 * 2] 11 echo $[(5 + 3) * 2] 16 echo $(( 5 + 4 )) 9 echo $(( 5 / 0 )) bash: 5/0: division by 0 ( error token is "0") 

11.3.6 Order of Expansion

When you are performing the expansion of variables, commands, arithmetic expressions, and pathnames, the shell is programmed to follow a specific order when scanning the command line. Assuming that the variables are not quoted, the processing is performed in the following order:

  1. Brace expansion

  2. Tilde expansion

  3. Parameter expansion

  4. Variable substitution

  5. Command substitution

  6. Arithmetic expansion

  7. Word splitting

  8. Pathname expansion

11.3.7 Arrays (Versions 2.x)

Versions of bash 2.x, provide for creation of one-dimensional arrays. Arrays allow you to collect a list of words into one variable name, such as a list of numbers, a list of names, or a list of files. Arrays are created with the built-in function declare -a, or can be created on the fly by giving a subscript to a variable name, such as x[0]=5. The index value is an integer starting at 0. There is no maximum size limit on the array, and indices do not have to be ordered numbers, i.e., x[0], x[1], x[2] . To extract an element of an array, the syntax is ${arrayname[index]}. If declare is given the -a and -r options, a read-only array is created.

FORMAT

declare -a variable_name variable = ( item1 item2 item3 ... ) 
Example 11.77
declare -a nums=(45 33 100 65) declare -ar names   (array is readonly) names=( Tom  Dick  Harry) states=( ME  [3]=CA  CT ) x[0]=55 n[4]=100 

When assigning values to an array, they are automatically started at index 0 and incremented by 1 for each additional element added. You do not have to provide indices in an assignment, and if you do, they do not have to be in order. To unset an array, use the unset command followed by the array name, and to unset one element of the array, use unset and the arrayname[subscript] syntax.

The declare, local, and read-only built-ins also can take the -a option to declare an array. The read command with the -a option is used to read in a list of words from standard input into array elements.

Example 11.78
1   $ declare -a friends 2   $ friends=(Sheryl Peter Louise) 3   $ echo ${friends[0]}     Sheryl 4   $ echo ${friends[1]}     Peter 5   $ echo ${friends[2]}     Louise 6   $ echo "All the friends are ${friends[*]}"     All the friends are Sheryl Peter Louise 7   $ echo "The number of elements in the array is ${#friends[*]}"     The number of elements in the array is 3 8   $ unset friends  or unset ${friends[*]} 

EXPLANATION

  1. The declare built-in command is used to explicitly declare an array, but it is not necessary. Any variable that uses a subscript, such as variable[0], when being assigned a value, will automatically be treated as an array.

  2. The array friends is assigned a list of values: Sheryl, Peter, and Louise.

  3. The first element of the friends array is accessed by enclosing the array name and its subscript in curly braces, with an index of 0 used as the value of the subscript. Sheryl is printed.

  4. The second element of the friends array is accessed by using the index value of 1.

  5. The third element of the friends array is accessed by using the index value of 2.

  6. When you place the asterisk within the subscript, all of the elements of the array can be accessed. This line displays all the elements in the friends array.

  7. The syntax ${#friends[*]} produces the size of the array; i.e., the number of elements in the array. On the other hand, ${#friends[0]} produces the number of characters in the value of the first element of the array. There are six characters in Sheryl.

  8. The unset built-in command deletes the whole array. Just one element of the array can be removed by typing: unset friends[1]; this would remove Sheryl.

Example 11.79
1   $ x[3]=100     $ echo ${x[*]}     100 2   $ echo ${x[0]} 3   $ echo ${x[3]}     100 4   $ states=(ME  [3]=CA  [2]=CT)     $ echo ${states[*]}     ME CA CT 5   $ echo ${states[0]}     ME 6   $ echo ${states[1]} 7   $ echo ${states[2]}     CT 8   $ echo ${states[3]}     CA 

EXPLANATION

  1. The third element of the array, x, is being assigned 100. It doesn't matter if the index number is 3, but because the first two elements do not exist yet, the size of the array is only 1. ${x[*]} displays the one element of the array, x.

  2. x[1] has no value, and neither do x[1] and x[2].

  3. x[3] has a value of 100.

  4. The states array is being assigned ME at index 0, CA at index 3, and CT at index 2. In this example, you can see that bash doesn't care at what index you store values, and that the index numbers do not have to be contiguous.

  5. The first element of the states array is printed.

  6. There is nothing stored in states[1].

  7. The third element of the states array, states[2], was assigned CT.

  8. The fourth element of the states array, states[3], was assigned CA.

11.3.8 An Introduction to Functions

Bash functions are used to execute a group of commands with a name within the context of the current shell (a child process is not forked). They are like scripts, only more efficient. Once defined, functions become part of the shell's memory so that when the function is called, the shell does not have to read it in from the disk as it does with a file. Often functions are used to improve the modularity of a script. Once defined, functions can be used again and again. Although functions can be defined at the prompt when running interactively, they are often defined in the user's initialization file, .bash_profile. They must be defined before they are invoked.

Defining Functions. There are two ways to declare a bash function. One way, the old Bourne shell way, is to give the function name followed by a set of empty parentheses, followed by the function definition. The new way (Korn shell way) is to use the function keyword followed by the function name and then the function definition. If using the new way, the parentheses are optional. The function definition is enclosed in curly braces. It consists of commands separated by semicolons. The last command is terminated with a semicolon. Spaces around the curly braces are required. Any arguments passed to the function are treated as positional parameters within the function. The positional parameters in a function are local to the function. The local built-in function allows local variables to be created within the function definition. Functions may also be recursive, i.e., call themselves an unlimited number of times.

FORMAT

function_name () { commands ; commands; } function function_name { commands ; commands; } function function_name () { commands ; commands; } 
Example 11.80
1   $ function greet { echo "Hello $LOGNAME, today is $(date)"; } 2   $ greet     Hello ellie, today is Wed Jul 14 14:56:31 PDT  2001 3   $ greet () { echo "Hello $LOGNAME, today is $(date)"; } 4   $ greet     Hello ellie, today is Wed Jul 14 15:16:22 PDT  2001 5   $ declare -f     declare -f greet()     {        echo "Hello $LOGNAME, today is $(date)"     } 6   $ declare -F[a]     declare -f greet 7   $ export -f greet 8   $ bash                 Start subshell 9   $ greet     Hello ellie, today is Wed Jul 14 17:59:24 PDT  2001 

[a] Only on bash version 2.x.

EXPLANATION

  1. The keyword function is followed by the name of the function, greet. The function definition is surrounded by curly braces. There must be a space after the opening curly brace. Statements on the same line are terminated with a semicolon.

  2. When the greet function is invoked, the command(s) enclosed within the curly braces are executed in the context of the current shell.

  3. The greet function is defined again using the Bourne shell syntax, the name of the function, followed by an empty set of parentheses, and the function definition.

  4. The greet function is invoked again.

  5. The declare command with the -f switch lists all functions defined in this shell and their definitions.

  6. The declare command with the -F switch lists only function names.

  7. The export command with the -f switch makes the function global, i.e., available to subshells.

  8. A new bash shell is started.

  9. The function is defined for this child shell because it was exported.

Example 11.81
1   $ function fun {          echo "The current working directory is $PWD."          echo "Here is a list of your files: "          ls          echo "Today is $(date +%A).";    } 2   $ fun     The current working directory is /home.     Here is a list of your files:     abc      abc123   file1.bak   none       nothing   tmp     abc1     abc2     file2       nonsense   nowhere   touch     abc122   file1    file2.bak   noone      one     Today is Wednesday. 3    $ function welcome { echo "Hi $1 and $2"; } 4    $ welcome tom joe      Hi tom and joe 5   $ set jane anna lizzy 6   $ echo $*     jane anna lizzy 7   $ welcome johan joe     hi johan and joe 8   $ echo  $1 $2     johan joe 9   $ unset -f welcome     # unsets the function 

EXPLANATION

  1. The function fun is named and defined. The keyword function is followed by the function's name and a list of commands enclosed in curly braces. Commands are listed on separate line; if they are listed on the same line, they must be separated by semicolons. A space is required after the first curly brace or you will get a syntax error. A function must be defined before it can be used.

  2. The function behaves just like a script when invoked. Each of the commands in the function definition are executed in turn.

  3. There are two positional parameters used in the function welcome. When arguments are given to the function, the positional parameters are assigned those values.

  4. The arguments to the function, tom and joe, are assigned to $1 and $2, respectively. The positional parameters in a function are private to the function and will not interfere with any used outside the function.

  5. The positional parameters are set at the command line. These variables have nothing to do with the ones set in the function.

  6. $* displays the values of the currently set positional parameters.

  7. The function welcome is called. Johan and joe are the values assigned to the positional parameters.

  8. The positional variables assigned at the command line are unaffected by those set in the function.

  9. The unset built-in command with the -f switch unsets the function. It is no longer defined.

Listing and Unsetting Functions. To list functions and their definitions, use the declare command. In bash versions 2.x and above, declare -F lists just function names. The function and its definition will appear in the output, along with the exported and local variables. Functions and their definitions are unset with the unset -f command.

11.3.9 Standard I/O and Redirection

When the shell starts up, it inherits three files: stdin, stdout, and stderr. Standard input normally comes from the keyboard. Standard output and standard error normally go to the screen. There are times when you want to read input from a file or send output or errors to a file. This can be accomplished by using I/O redirection. See Table 11.23 for a list of redirection operators.

Table 11.23. Redirection
Redirection Operator What It Does
< Redirects input.
> Redirects output.
>> Appends output.
2> Redirects error.
&> Redirects output and error.
>& Redirects output and error (preferred way).
2>&1 Redirects error to where output is going.
1>&2 Redirects output to where error is going.
>| Overrides noclobber when redirecting output.
<> filename Uses file as both standard input and output if a device file (from /dev).
Example 11.82
1   $ tr '[A-Z]'  '[a-z]' < myfile   # Redirect  input 2   $ ls > lsfile                    # Redirect output     $ cat lsfile     dir1     dir2     file1     file2     file3 3   $ date >> lsfile                 # Redirect and append otuput     $ cat lsfile     dir1     dir2     file1     file2     file3     Sun Sept 17 12:57:22 PDT 2001 4   $ cc prog.c 2> errfile           # Redirect error 5   $ find . -name \*.c -print > foundit 2> /dev/null     # Redirect output to foundit and errors to /dev/null,     # respectively. 6   $ find . -name \*.c -print >& foundit     # Redirect both output and errors to foundit. 7   $ find . -name \*.c -print > foundit 2>&1     # Redirect output to foundit and send errors to where output     # is going; i.e. foundit 8   $ echo "File needs an argument" 1>&2     # Send standard output to error 

EXPLANATION

  1. Instead of getting input from the keyboard, standard input is redirected from the file myfile to the UNIX tr command. All uppercase letters are converted to lowercase.

  2. Instead of sending output to the screen, the ls command redirects its output to the file lsfile.

  3. The output of the date command is redirected and appended to lsfile.

  4. The C program source file prog.c is compiled. If the compile fails, the standard error is redirected to the file errfile. Now you can take your error file to the local guru for an explanation (of sorts)!

  5. The find command starts searching in the current working directory for filenames ending in .c, and prints the filenames to a file named foundit. Errors from the find command are sent to /dev/null.

  6. The find command starts searching in the current working directory for filenames ending in .c, and prints the filenames to a file named foundit. The errors are also sent to foundit.

  7. Same as 6.

  8. The echo command sends its message to standard error. Its standard output is merged with standard error.

The exec Command and Redirection. The exec command can be used to replace the current program with a new one without starting a new process. Standard output or input can be changed with the exec command without creating a subshell. (See Table 11.24.) If a file is opened with exec, subsequent read commands will move the file pointer down the file a line at a time until the end of the file. The file must be closed to start reading from the beginning again. However, if using UNIX utilities such as cat and sort, the operating system closes the file after each command has completed.

Table 11.24. The exec Command
exec Command What It Does
exec ls ls executes in place of the shell. When ls is finished, the shell in which it was started does not return.
exec < filea Opens filea for reading standard input.
exec > filex Opens filex for writing standard output.
exec 3< datfile Opens datfile as file descriptor 3 for reading input.
sort <&3 Datfile is sorted.
exec 4>newfile Opens newfile as file descriptor (fd) 4 for writing.
ls >&4 Output of ls is redirected to newfile.
exec 5<&4 Makes fd 5 a copy of fd 4.
exec 3<&- Closes fd 3.
Example 11.83
1   $ exec date     Thu Oct 14 10:07:34  PDT 2001      <Login prompt appears if you are in your login shell > 2   $ exec > temp     $ ls     $ pwd     $ echo Hello 3   $ exec > /dev/tty 4   $ echo Hello     Hello 

EXPLANATION

  1. The exec command executes the date command in the current shell (does not fork a child shell). Because the date command is executed in place of the current shell, when the date command exits, the shell terminates. If a bash shell had been started from the TC shell, the bash shell would exit and the TC shell prompt would appear. If you are in your login shell when you try this, you will be logged out. If you are working interactively in a shell window, the window exits.

  2. The exec command opens standard output for the current shell to the temp file. Output from ls, pwd, and echo will no longer go to the screen, but to temp. (See Figure 11.3.)

    Figure 11.3. The exec command and file descriptors.

    graphics/11fig03.gif

  3. The exec command reopens standard output to the terminal. Now, output will go to the screen as shown in line 4.

  4. Standard output has been directed back to the terminal (/dev/tty).

Example 11.84
1   > bash 2   $ cat doit     pwd     echo hello     date 3   $ exec < doit     /home/homebound/ellie/shell     hello     Thu Oct 14 10:07:34  PDT 2001 4   > 

EXPLANATION

  1. From a TC shell prompt, bash is started up. (This is done so that when the exec command exits, the user will not be logged out.)

  2. The contents of a file called doit are displayed.

  3. The exec command opens standard input to the file called doit. Input is read from the file instead of from the keyboard. The commands from the file doit are executed in place of the current shell. When the last command exits, so does the shell.

  4. The bash shell exited when the exec command completed. The TC shell prompt appeared. It was the parent shell. If you had been in your login shell when the exec finished, you would be logged out; if in a window, the window would have disappeared.

Example 11.85
1   $ exec 3> filex 2   $ who >& 3 3   $ date >& 3 4   $ exec 3>&- 5   $ exec 3<filex 6   $ cat <&3     ellie  tty    Jul 21 09:50     ellie  ttyp1  Jul 21 11:16  (:0.0)     ellie  ttyp0  Jul 21 16:49  (:0.0)     Wed Jul 21 17:15:18 PDT 2001 7   $ exec 3<&- 8   $ date >& 3     date: write error: Bad file descriptor 

EXPLANATION

  1. File descriptor 3 (fd 3) is assigned to filex and opened for redirection of output. See Figure 11.4(a).

    Figure 11.4. exec and file descriptors.

    graphics/11fig04.gif

  2. The output of the who command is sent to fd 3, filex.

  3. The output of the date command is sent to fd 3; filex is already opened, so the output is appended to filex.

  4. Fd 3 is closed.

  5. The exec command opens fd 3 for reading input. Input will be redirected from filex. See Figure 11.4(b).

  6. The cat program reads from fd 3, assigned to filex.

  7. The exec command closes fd 3. (Actually, the operating system will close the file once end of file is reached.)

  8. When attempting to send the output of the date command to fd 3, bash reports an error condition, because fd 3 was previously closed.

11.3.10 Pipes

A pipe takes the output from the command on the left-hand side of the pipe symbol and sends it to the input of the command on the right-hand side of the pipe symbol. A pipeline can consist of more than one pipe.

The purpose of the commands in Example 11.86 is to count the number of people logged on (who), save the output of the command in a file (tmp), use the wc -l to count the number of lines in the tmp file (wc -l), and then remove the tmp file (i.e., find the number of people logged on).

Example 11.86
1  $ who > tmp 2  $ wc -l tmp    4 tmp 3  $ rm tmp # Using a pipe saves disk space and time. 4  $ who | wc -l    4 5  $ du .. | sort -n | sed -n '$p'    1980 6  $ ( du / | sort -n | sed -n '$p' ) 2> /dev/null    1057747  / 

EXPLANATION

  1. The output of the who command is redirected to the tmp file.

  2. The wc -l command displays the number of lines in tmp.

  3. The tmp file is removed.

  4. With the pipe facility, you can perform all three of the preceding steps in one step. The output of the who command is sent to an anonymous kernel buffer; the wc \_l command reads from the buffer and sends its output to the screen. See Figure 11.5.

    Figure 11.5. The pipe.

    graphics/11fig05.gif

  5. The output of the du command, the number of disk blocks used per directory, starting in the parent directory (..), is piped to the sort command and sorted numerically. It is then piped to the sed command, which prints the last line of the output it receives. See Figure 11.6.

    Figure 11.6. Multiple pipes (filter).

    graphics/11fig06.gif

  6. The du command (starting in the root directory) will send error messages to stderr (the screen) if it is unable to get into a directory because the permissions have been turned off. When you put the whole command line in a set of parentheses, all the output is sent to the screen, and all the errors are directed to the UNIX bit bucket, /dev/null.

11.3.11 The here document and Redirecting Input

The here document is a special form of quoting. It accepts inline text for a program expecting input, such as mail, sort, or cat, until a user-defined terminator is reached. It is often used in shell scripts for creating menus. The command receiving the input is appended with a << symbol, followed by a user-defined word or symbol, and a newline. The next lines of text will be the lines of input to be sent to the command. The input is terminated when the user-defined word or symbol is then placed on a line by itself in the leftmost column (it cannot have spaces surrounding it). The word is used in place of Control-D to stop the program from reading input.

If the terminator is preceded by the <<- operator, leading tabs, and only tabs, may precede the final terminator. The user-defined terminating word or symbol must match exactly from "here" to "here." The following examples illustrate the use of the here document at the command line to demonstrate the syntax. It is much more practical to use them in scripts.

Example 11.87

graphics/11prfig02.gif

EXPLANATION

  1. The UNIX cat program will accept input until the word FINISH appears on a line by itself.

  2. A secondary prompt appears. The following text is input for the cat command. Variable substitution is performed within the here document.

  3. Command substitution, $(date +%T), is performed within the here document. Could have also used the older form of command substitution: 'date +T'.

  4. The user-defined terminator FINISH marks the end of input for the cat program. It cannot have any spaces before or after it and is on a line by itself.

  5. The output from the cat program is displayed.

  6. The shell prompt reappears.

Example 11.88
1   $ cat <<- DONE     >  Hello there     >     What's up?     >Bye now The time is 'date'. 2   >   DONE       Hello there            What's up?     Bye now The time is Sun Feb 819:48:23 PST 2001.     $ 

EXPLANATION

  1. The cat program accepts input until DONE appears on a line by itself. The <<- operator allows the input and final terminator to be preceded by one or more tabs. Typing this example at the command line may cause problems with the Tab key; the example will work fine, if run from a script.

  2. The final matching terminator, DONE, is preceded by a tab. The output of the cat program is displayed on the screen.

11.3.12 Shell Invocation Options

When the shell is started using the bash command, it can take options to modify its behavior. There are two types of options: single-character options and multicharacter options. The single-character options consist of a single leading dash followed by a single character. The multicharacter options consist of two leading dashes and any number of characters. Multicharacter options must appear before single-character options. An interactive login shell normally starts up with -i (starts an interactive shell) , -s (reads from standard input), and -m (enables job control). See Table 11.25.

Table 11.25. Bash 2.x Shell Invocation Options
Option Meaning
-c string Commands are read from string. Any arguments after string are assigned to positional parameters, starting at $0.
-D A list of double quoted strings, preceded by a $, are printed to standard output. These strings are subject to language translation when the current locale is not C or POSIX.The -n option is implied; no commands will be executed.
-i Shell is in the interactive mode. TERM, QUIT, and INTERRUPT are ignored.
-s Commands are read from standard input and allows the setting of positional parameters.
-r Starts a restricted shell.
- - Signals the end of options and disables further option processing. Any arguments after - - or - are treated as filenames and arguments.
- -dump-strings Same as -D.
- -help Displays a usage message for a built-in command and exits.
- -login Causes bash to be invoked as a login shell.
- -noediting When bash is running interactively, does not use the Readline library.
- -noprofile When starting up, bash does not read the initialization files: /etc/profile, ~/.bash_profile, ~/.bash_login, or ~/.profile.
- -norc For interactive shells, bash will not read the ~/.bashrc file. Turned on by default, if running shell as sh.
- -posix Changes the behavior of bash to match the POSIX 1003.2 standard, if otherwise it wouldn't.
- -quiet Displays no information at shell startup, the default.
- -rcfile file If bash is interactive, uses this intialization file instead of ~/.bashrc.
- -restricted Starts a restricted shell.
- -verbose Turns on verbose; same as -v.
- -version Displays version information about this bash shell and exits.

11.3.13 The set Command and Options

The set command can be used to turn shell options on and off, as well as for handling command line arguments. To turn an option on, the dash ( ) is prepended to the option; to turn an option off, the plus sign (+) is prepended to the option. See Table 11.26 for a list of set options.

Example 11.89
1   $ set -f 2   $ echo *     * 3   $ echo ??     ?? 4   $ set +f 

EXPLANATION

  1. The f option is turned on, disabling filename expansion.

  2. The asterisk is not expanded.

  3. The question marks are not expanded.

  4. The f is turned off; filename expansion is enabled.

 

Table 11.26. The Built-In set Command Options
Name of Option Shortcut Switch What It Does
allexport -a Automatically marks new or modified variables for export from the time the option is set, until unset.
braceexpand -B Enables brace expansion, and is a default setting.
emacs   For command line editing, uses the emacs built-in editor, and is a default setting.
errexit -e If a command returns a nonzero exit status (fails), exits. Not set when reading initialization files.
histexpand -H Enables ! and !! when performing history substitution, and is a default setting.
history   Enables command line history; on by default.
ignoreeof   Disables EOF (Control-D) from exiting a shell; must type exit. Same as setting shell variable, IGNOREEOF=10.
keyword -k Places keyword arguments in the environment for a command.
interactive_comments   For interactive shells, a leading # is used to comment out any text remaining on the line.
monitor -m Allows job control.
noclobber -C Protects files from being overwritten when redirection is used.
noexec -n Reads commands, but does not execute them. Used to check the syntax of scripts. Not on when running interactively.
noglob -d Disables pathname expansion; i.e., turns off wildcards.
notify -b Notifies user when background job finishes.
nounset -u Displays an error when expanding a variable that has not been set.
onecmd -t Exits after reading and executing one command.
physical -P If set, does not follow symbolic links when typing cd or pwd. The physical directory is used instead.
posix   Shell behavior is changed if the default operation doesn't match the POSIX standard.
privileged -p When set, the shell does not read the .profile or ENV file and shell functions are not inherited from the environment; automatically set for setuid scripts.
verbose -v Turns on the verbose mode for debugging.
vi   For command line editing, uses the vi built-in editor.
xtrace -x Turns on the echo mode for debugging.

11.3.14 The shopt Command and Options

The shopt (bash 2.x) command can also be used to turn shell options on and off.

Table 11.27. The shopt Command Options
Option Meaning
cdable_vars If an argument to the cd built-in command is not a directory, it is assumed to be the name of a variable whose value is the directory to change to.
cdspell Corrects minor errors in the spelling of a directory name in a cd command. The errors checked for are transposed characters, a missing character, and a character too many. If a correction is found, the corrected path is printed, and the command proceeds. Only used by interactive shells.
checkhash Bash checks that a command found in the hash table exists before trying to execute it. If a hashed command no longer exists, a normal path search is performed.
checkwinsize Bash checks the window size after each command and, if necessary, updates the values of LINES and COLUMNS.
cmdhist Bash attempts to save all lines of a multiple-line command in the same history entry. This allows easy re-editing of multiline commands.
dotglob Bash includes filenames beginning with a dot (.) in the results of filename expansion.
execfail A noninteractive shell will not exit if it cannot execute the file specified as an argument to the exec built-in command. An interactive shell does not exit if exec fails.
expand_aliases Aliases are expanded. Enabled by default.
extglob The extended pattern matching features (regular expression metacharacters derived from Korn shell for filename expansion) are enabled.
histappend The history list is appended to the file named by the value of the HISTFILE variable when the shell exits, rather than overwriting the file.
histreedit If readline is being used, a user is given the opportunity to re-edit a failed history substitution.
histverify If set, and readline is being used, the results of history substitution are not immediately passed to the shell parser. Instead, the resulting line is loaded into the readline editing buffer, allowing further modification.
hostcomplete If set, and readline is being used, bash will attempt to perform hostname completion when a word containing @ is being completed. Enabled by default.
huponexit If set, bash will send SIGHUP (hangup signal) to all jobs when an interactive login shell exits.
interactive_comments Allows a word beginning with # to cause that word and all remaining characters on that line to be ignored in an interactive shell. Enabled by default.
lithist If enabled, and the cmdhist option is enabled, multiline commands are saved to the history with embedded newlines rather than using semicolon separators where possible.
mailwarn If set, and a file that bash is checking for mail has been accessed since the last time it was checked, the message The mail in mailfile has been read is displayed.
nocaseglob If set, bash matches filenames in a case-insensitive fashion when performing filename expansion.
nullglob If set, bash allows filename patterns that match no files to expand to a null string, rather than themselves.
promptvars If set, prompt strings undergo variable and parameter expansion after being expanded. Enabled by default.
restricted_shell The shell sets this option if it is started in restricted mode. The value may not be changed. This is not reset when the startup files are executed, allowing the startup files to discover whether or not a shell is restricted.
shift_verbose If this is set, the shift built-in prints an error message when the shift count exceeds the number of positional parameters.
sourcepath If set, the source built-in uses the value of PATH to find the directory containing the file supplied as an argument. Enabled by default.
source A synonym for dot (.).

11.3.15 Shell Built-In Commands

The shell has a number of commands that are built-in to its source code. Because the commands are built-in, the shell doesn't have to locate them on disk, making execution much faster. The help feature provided with bash gives you online help for any built-in command. The built-in commands are listed in Table 11.28.

Table 11.28. Built-In Commands
Command What It Does
: Do-nothing command; returns exit status zero.
. file The dot command reads and executes command from file.
break [n] See "Loop Control".
. Executes program in context of current process; same as source.
alias Lists and creates "nicknames" for existing commands.
bg Puts a job in the background.
bind Display current key and function bindings, or binds keys to a readline function or macro.
break Breaks out of the innermost loop.
builtin [sh-builtin [args]] Runs a shell built-in, passing it args and returning 0 exit status. Useful if a function and built-in have the same name.
cd [arg] Changes the directory to home if no arg or to value of arg.
command command [arg] Runs a command even if a function has the same name; i.e., bypasses function lookup.
continue [n] See "Loop Control".
declare [var] Displays all variables or declares variables with optional attributes.
dirs Displays a list of currently remembered directories resulting from pushd.
disown Removes an active job from the job table.
echo [args] Displays args terminated with a newline.
enable Enables and disables shell built-in commands.
eval [args] Reads args as input to the shell and executes the resulting command(s).
exec command Runs command in place of this shell.
exit [n] Exits the shell with status n.
export [var] Makes var known to subshells.
fc History's fix command for editing history commands.
fg Puts background job into foreground.
getopts Parses and processes command line options.
hash Controls the internal hash table for quicker searches for commands.
help [command] Displays helpful info about built-in commands and, if command is specified, detailed help about that built-in command.
history Displays the history list with line numbers.
jobs Lists jobs put in the background.
kill [-signal process ] Sends the signal to the PID number or job number of the process. Type at the prompt: kill -l.
getopts Used in shell scripts to parse command line and check for legal options.
let Used for evaluating arithmetic expressions and assigning results of arithmetic calculations to variables.
local Used in functions to restrict the scope of variables to the function.
logout Exits the login shell.
popd Removes entries from the directory stack.
pushd Adds entries to the directory stack.
pwd Prints present working directory.
read [var] Reads line from standard input into variable var.
readonly [var] Makes variable var read-only. Cannot be reset.
return [n] Returns from a function where n is the exit value given to the return.
set Sets options and positional parameters. See "The set Command and Positional Parameters".
shift [n] Shifts positional parameters to the left n times.
stop pid Halts execution of the process number PID.
suspend Stops execution of the current shell (but not if a login shell).
test Checks file types and evaluates conditional expressions.
times Prints accumulated user and system times for processes run from this shell.
trap [arg] [n] When shell receives signal n ( 0, 1, 2, or 15 ), executes arg.
type [command] Prints the type of command; e.g., pwd is a built-in shell command.
typeset Same as declare. Sets variables and gives them attributes.
ulimit Diplays and sets process resource limits.
umask [octal digits] Sets user file creation mode mask for owner, group, and others.
unalias Unsets aliases.
unset [name] Unset value of variable or function.
wait [pid#n] Waits for background process with PID number n and reports termination status.

BASH SHELL LAB EXERCISES

Lab 43: Getting Started

1:

What process puts the login prompt on your screen?

2:

What process assigns values to HOME, LOGNAME, and PATH?

3:

How do you know what shell you are using?

4:

What command will allow you to change your login shell?

5:

Where is your login shell assigned? (What file?)

6:

Explain the difference between the /etc/profile and ~/.bash_profile file.

7:

Which one is executed first?

8:

Edit your .bash_profile file as follows:

  1. Welcome the user.

  2. Add your home directory to the path if it is not there.

  3. Set erase to the Backspace key using stty.

  4. Type source.bash_profile. What is the function of the source command?

9:

What is the BASH_ENV file? When is it executed?

10:

What is the default primary prompt?

  1. Change the prompt to include the time of day and your home directory.

  2. What is the default secondary prompt? What is its function?

11:

Explain the function of each of the following settings:

  1. set -o ignoreeof

  2. set -o noclobber

  3. set -o emacs

  4. set-o vi

12:

In what file are the settings in the previous example stored? Why are they stored there?

13:

What does shopt -p do? Why use shopt instead of set?

14:

What is a built-in command? How can you tell if a command is a built-in or an executable? What is the purpose of the builtin command? The enable command?

15:

What would cause the shell to return an exit status of 127?

Lab 44: Job Control

1:

What is the difference between a program and a process? What is a job?

2:

What is the PID of your shell?

3:

How do you stop a job?

4:

What command brings a background job into the foreground?

5:

How do you list all running jobs? All stopped jobs?

6:

What is the purpose of the kill command?

7:

What does jobs -l display? What does kill -l display?

Lab 45: Command Completion, History, and Aliases

1:

What is filename completion?

2:

What is the name of the file that stores a history of commands entered at the command line?

3:

What does the HISTSIZE variable control? What does HISTFILESIZE control?

4:

What does bang, bang mean?

5:

How would you reexecute the last command that started with a v?

6:

How would you reexecute the 125th command? How would you print the history list in reverse?

7:

How do you set interactive editing to use the vi editor? In what initialization file would you put this setting?

8:

What is the fc command?

9:

What is the purpose of the Readline library? From what initialization file does it read instructions?

10:

What is key binding? How do you find out what keys are bound?

11:

What is the universal argument?

12:

Create an alias for the following commands:

  1. clear

  2. fc -s

  3. ls - -color=tty

  4. kill -l

Lab 46: Shell Metacharacters

1:

Make a directory called wildcards. Cd to that directory and type at the prompt:

touch ab abc a1 a2 a3 all a12 ba ba.1 ba.2 filex filey AbC ABC ABc2 abc 
2:

Write and test the command that will do the following:

  1. List all files starting with a.

  2. List all files ending in at least one digit.

  3. List all files starting with a or A.

  4. List all files ending in a period, followed by a digit.

  5. List all files containing just two alphabetic characters.

  6. List three character files where all letters are uppercase.

  7. List files ending in 10, 11, or 12.

  8. List files ending in x or y.

  9. List all files ending in a digit, an uppercase letter, or a lowercase letter.

  10. List all files not starting with a b or B.

  11. Remove two character files starting with a or A.

Lab 47: Redirection

1:

What are the names of the three file streams associated with your terminal?

2:

What is a file descriptor?

3:

What command would you use to do the following:

  1. Redirect the output of the ls command to a file called lsfile?

  2. Redirect and append the output of the date command to lsfile?

  3. Redirect the output of the who command to lsfile? What happened?

4:

What happens when you type cp all by itself?

5:

How do you save the error message from the above example to a file?

6:

Use the find command to find all files, starting from the parent directory, of type directory. Save the standard output in a file called found and any errors in a file called found.errs.

7:

Take the output of three commands and redirect the output to a file called gottem_all?

8:

Use a pipe(s) with the ps and wc commands to find out how many processes you are currently running.

Lab 48: Variables

1:

What is a positional parameter? Type at the command line:

set dogs cats birds fish 
  1. How do you list all of the positional parameters?

  2. Which positional parameter is assigned birds?

  3. How do you print the number of positional parameters?

  4. How do you remove all the positional parameters from the shell's memory?

2:

What is an environment variable? What is the command used to list them? Create an environment variable called CITY and assign it the value of your home town. How do you export it?

3:

What is a local variable? Set a local variable to your name. Print its value. Unset it.

4:

What is the function of declare -i?

5:

What does the $$ variable display? What does the $! display?

[1]  Although bash is traditionally the default shell for Linux platforms, it now comes bundled with Solaris 8.

[2]  To get the latest version of bash, visit http://www.delorie.com/gnu/.

[3]  There are a number of different initialization files used by bash; they are discussed on the next pages.

[4]  If the shell is invoked with the -noprofile option, none of the initialization files are read.

[5]  If the set -o (editor) has not been set, but the EDITOR variable has been set to either emacs or vi, then bash will use that definition.

[6]   vi is case-sensitive; an uppercase J and a lowercase j are different commands.

[7]  Whether the user saves and quits the editor, or simply quits the editor, the commands will all be executed, unless they are commented or deleted.

[8]  The tilde character will not be expanded if enclosed in either double or single quotes.

[9]  Bash Reference Manual: http://www.delorie.com/gnu/docs/bash/bashref_56.html.

[10]  A variable set to a value or to null will be displayed by using the set command, but an unset variable will not.

[11]  Like DNA, inheritance goes one direction only, from parent to child.

[12]  On bash versions 2.x, printf is a built-in command.

[13]  The bash shell allows backquotes for command substitution for upward-compatibility, but provides an alternate method as well.

CONTENTS


UNIX Shells by Example
UNIX Shells by Example, 3rd Edition
ISBN: 013066538X
EAN: 2147483647
Year: 2001
Pages: 18
Authors: Ellie Quigley

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net