8.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 alpha or underscore character. The remaining characters can be alphas, 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 white space 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 simply to assign a value to a variable in the format:

Format

variable=value

Example 8.53.
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 thedeclare built-in command." [11] So from this point on we'll use the declare built-in (even though we could just as easily have chosen to use typeset).

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

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 8.54.
declare name=Tommy

Table 8.17. 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 Lists just function names

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

8.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 white space surrounding the equal sign. To set the variable to null, the equal sign is followed by a newline.[12]

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

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 360.)

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 8.55.

Example 8.55.
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 white space 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 8.56.
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 8.57.
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 white space.

  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.

8.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.[13] 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 8.19 for a list of environment variables.

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

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 dollar sign on a variable when exporting it.)

Format

export variable=value
variable=value; export variable
declare -x variable=value

Example 8.58.
export NAME=john
PS1= `d:W:$USER> ` ; export PS1
declare -x TERM=linux

Table 8.18. 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 8.59.
1  $ export
							TERM=linux
							or
							declare -x TERM=linux

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 linux. 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 8.19. 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.
BASH_VERSION Expands to the version number of this instance of bash.
BASH_VERSINFO[*] Version information about this version of bash if the version is 2.0 or above.
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.
EDITOR Pathname for a built-in editor: emacs, gmacs, or vi.
EUID Expands to the effective user ID of the current user, initialized at shell startup.
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.
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:~.
GLOBIGNORE[*] A list of files that will be ignored during filename expansion (called globbing).
GROUPS[*] An array of groups to which the current user belongs.
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 which 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_.
LC_ALL[*] Overrides the value of LANG and any other LC_ variable.
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.
LC_MESSSAGES[*] Determines the locale used to translate double-quoted strings preceded by 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.
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.
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. "
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.
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 thegetopts 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.
PROMPT_COMMAND The command assigned to this variable is executed before the primary prompt is displayed.
PPID Process id of the parent process.
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 RANDO 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 bashis started.
TMOUT Specifies number of seconds to wait for input before exiting.
FORMAT Used to format the output of the timereserved word on a command pipeline .
UID Expands to the user ID of the current user, initialized at shell startup.

[*] only on version of bash 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 8.60.
							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 8.20 lists the echo options and escape sequences.

Table 8.20. 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)
 Backspace
c Prints the line without a newline
f Form feed
Newline
Return
Tab
v Vertical tab
\ Backslash
nn 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 8.61.
1 $ echo The username is $LOGNAME.
							The username is ellie.

2  $ echo -e "		Hello therec"
							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 [14] 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.

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

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 8.62.
printf "%10.2f%5d
" 10.5  25

Table 8.21. Format Specifiers for the printf Command
Format specifier Value
" Double quote
NNN An octal character where NNN represents 0 to 3 digits
\ Backslash
a Alert or beep
 Backspace
c Produce no further output
f Form feed
New line
Carriage return
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 8.63.
1  $ printf --version
							printf (GNU sh-utils) 1.16

2  $ type printf
							printf is a shell builtin

3  $ printf "The number is %.2f
" 100
							The number is 100.00

4  $ printf "%-20s%-15s%10.2f
" "Jody" "Savage" 28
							Jody                Savage              28.00

5  $ printf "|%-20s|%-15s|%10.2f|
" "Jody" "Savage" 28
							Jody                |Savage         |     28.00|

6  $ printf "%s
							'
							s average was %.1f%%.
" "Jody" $(( (80+70+90)/3 ))
							Jody's average was 80.0%.
						

Explanation

  1. The Gnu version of the printf command is printed. This is not a built-in command, but a Linux executable found in /usr/bin.

  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 printing, designated by the format specification %.2f in the format string. Note that unlike C, there are no commas separating the arguments.

  4. This time 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 those 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 stringJody and formats the result of the arithmetic expansion. (See "Arithmetic Expansion" on page 356.) Two percents (%%) 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 8.22 for a list of variable modifiers.

Table 8.22. 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} [a] Gets the substring of the value in variable, starting at offset, where offset starts at 0 to the end of the string.
${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.

[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 8.64.
(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 8.65.
(Substitute Permanent Default Values)
1  $ name=

2  $ echo  ${name:=Peter}
							Peter

3  $ echo $name
							Patty

4  $ echo ${EDITOR:=/bin/vi}
							/bin/vi

5  $ echo $EDITOR
							/bin/vi
						

Explanation

  1. The variable name is assigned the value null.

  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 8.66.
(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 8.67.
(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 8.68.
(Creating Substring[a])

1 $ var=notebook

2 $ echo ${var:0:4}
							note

3 $ echo ${var:4:4}
							book

4 $ echo ${var:0:2}
							no
						

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 8.23.

Table 8.23. 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 in versions of bash prior to 2.x.

Example 8.69.
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 8.70.
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 8.71.
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 8.72.
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 8.73.
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 8.24.

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 8.24. Positional Parameters
Expression Function
$0 References the name of the current shell script.
$1–$9 Positional parameters 19.
${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 8.74.
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 8.25.

Table 8.25. 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 8.75.
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.

8.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 8.26 are special to the shell and must be quoted.

Table 8.26. 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 back quotes) 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 ($), back quotes (` `), and the backslash from interpretation if enclosed in double quotes.

Example 8.76.
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	 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 8.77.
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 8.78.
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 2000
						

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.)

8.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 back quotes to perform command substitution.[15] Bash allows two forms: the older form, where the command(s) is placed within back quotes, and the new Korn style form, where the command(s) is placed within a set of parentheses preceded by a dollar sign.

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

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

`Linux command`   Old method with back quotes
$(Linux command)  New method
					

Example 8.79.
						(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 1999
6 $ echo $2 $6
						Jul 1999

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 back quotes, 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. White space 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 white space.

  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 Linux 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 back quotes in command substitution is presented below in Example 8.80.

Example 8.80.
(The New Way)
1 $ d=$(date)
  $ echo $d
						Wed Jul 14 09:35:21 PDT 1999

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 1999 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 1999
						    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.

8.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 page394.

There are two formats for evaluating arithmetic expressions:

Format

$[ expression ]
$(( expression ))

Example 8.81.
						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")
					

8.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

8.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 8.82.
						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 8.83.
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 8.84.
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.

8.3.8. Functions (Introduction)

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 8.85.
1 $ function greet { echo "Hello $LOGNAME, today is $(date)"; }
2 $ greet
							Hello ellie, today is Wed Jul 14 14:56:31 PDT 1999

3 $ greet () { echo "Hello $LOGNAME, today is $(date)"; }
4 $ greet
							Hello ellie, today is Wed Jul 14 15:16:22 PDT 1999

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 1999
						

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 8.86.
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.

8.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 8.27 for a list of redirection operators.

Table 8.27. 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 8.87.
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 1999

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 Linux 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 8.28 below.) 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 Linux utilities such as cat and sort, the operating system closes the file after each command has completed.

Table 8.28. 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 8.88.
1 $ exec date
							Thu Oct 14 10:07:34 PDT 1999
							<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 tcshell, the bash shell would exit and the tcshell 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 8.3.)

    Figure 8.3. The exec command and file descriptors.

  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 8.89.
1 > bash
2 $ cat doit
							pwd
							echo hello
							date
3 $ exec < doit
							/home/homebound/ellie/shell
							hello
							Thu Oct 14 10:07:34 PDT 1999
4 >

Explanation

  1. From a tcshell 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 tcshell 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 8.90.
1 $ exec 3> filex
2 $ who >& 3
3 $ date >& 3
4 $ exec 3>-
5 $ exec 3<filex
6 $ cat <&3
							ellietty1   Jul 21 09:50
							elliettyp1  Jul 21 11:16  (:0.0)
							elliettyp0  Jul 21 16:49  (:0.0)
							Wed Jul 21 17:15:18 PDT 1999
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 8.4(a).

    Figure 8.4. Exec and file descriptors.

  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 8.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.

8.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 next commands in Example 8.91 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 8.91.
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 8.5.

    Figure 8.5. The pipe.

  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 8.6.

    Figure 8.6. Multiple pipes (filter).

  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 Linux bit bucket, /dev/null.

8.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 8.92.

Explanation

  1. The Linux 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 8.93.
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 1999.
  $

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.

8.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 8.29.

Table 8.29. 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.

8.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 8.30 for a list of set options.

Example 8.94.
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 8.30. 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.
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.

8.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 8.31. 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 "." 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 which 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. (a dot)

8.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 give you online help for any built-in command. The built-in commands are listed in Table 8.32.

Table 8.32. 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 "Looping Commands" on page440.
. 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 arg.
command command [arg] Runs a command even if a function has the same name; i.e., bypasses function lookup.
continue [n] See "Looping Commands" on page440.
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" on page 397.
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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.18.101