Parameters and Variables


Variables


Within a shell, a shell parameter is associated with a value that is accessible to the user. There are several kinds of shell parameters. Parameters whose names consist of letters, digits, and underscores are often referred to as shell variables, or simply variables. A variable name must start with a letter or underscore, not with a number. Thus A76, MY_CAT, and ___X___ are valid variable names, whereas 69TH_STREET (starts with a digit) and MY-NAME (contains a hyphen) are not.

User-created variables


Shell variables that you name and assign values to are user-created variables. You can change the values of user-created variables at any time, or you can make them readonly so that their values cannot be changed. You can also make user-created variables global. A global variable (also called an environment variable) is available to all shells and other programs you fork from the original shell. One naming convention is to use only uppercase letters for global variables and to use mixed-case or lowercase letters for other variables. Refer to "Locality of Variables" on page 916 for more information on global variables.

To assign a value to a variable in the Bourne Again Shell, use the following syntax:


VARIABLE=value

There can be no whitespace on either side of the equal sign (=). An example assignment follows:

$ myvar=abc


The Bourne Again Shell permits you to put variable assignments on a command line. These assignments are local to the command shellthat is, they apply to the command only. The my_script shell script displays the value of TEMPDIR. The following command runs my_script with TEMPDIR set to /home/sam/temp. The echo builtin shows that the interactive shell has no value for TEMPDIR after running my_script. If TEMPDIR had been set in the interactive shell, running my_script in this manner would have had no effect on its value.

$ cat my_script echo $TEMPDIR $ TEMPDIR=/home/sam/temp my_script /home/sam/temp $ echo $TEMPDIR $


Keyword variables


Keyword shell variables (or simply keyword variables) have special meaning to the shell and usually have short, mnemonic names. When you start a shell (by logging in, for example), the shell inherits several keyword variables from the environment. Among these variables are HOME, which identifies your home directory, and PATH, which determines which directories the shell searches and in what order to locate commands that you give the shell. The shell creates and initializes (with default values) other keyword variables when you start it. Still other variables do not exist until you set them.

You can change the values of most of the keyword shell variables at any time but it is usually not necessary to change the values of keyword variables initialized in the /etc/profile or /etc/csh.cshrc systemwide startup files. If you need to change the value of a bash keyword variable, do so in one of your startup files (page 267). Just as you can make user-created variables global, so you can make keyword variables global; this is usually done automatically in the startup files. You can also make a keyword variable readonly.

Positional and special parameters


The names of positional and special parameters do not resemble variable names. Most of these parameters have one-character names (for example, 1, ?, and #) and are referenced (as are all variables) by preceding the name with a dollar sign ($1, $?, and $#). The values of these parameters reflect different aspects of your ongoing interaction with the shell.

Whenever you give a command, each argument on the command line becomes the value of a positional parameter. Positional parameters (page 920) enable you to access command line arguments, a capability that you will often require when you write shell scripts. The set builtin (page 924) enables you to assign values to positional parameters.

Other frequently needed shell script values, such as the name of the last command executed, the number of command line arguments, and the status of the most recently executed command, are available as special parameters. You cannot assign values to special parameters.

User-Created Variables

The first line in the following example declares the variable named person and initializes it with the value alex:

$  person=alex $  echo person person $ echo $person alex


Because the echo builtin copies its arguments to standard output, you can use it to display the values of variables. The second line of the preceding example shows that person does not represent alex. Instead, the string person is echoed as person. The shell substitutes the value of a variable only when you precede the name of the variable with a dollar sign ($). The command echo $person displays the value of the variable person; it does not display $person because the shell does not pass $person to echo as an argument. Because of the leading $, the shell recognizes that $person is the name of a variable, substitutes the value of the variable, and passes that value to echo. The echo builtin displays the value of the variablenot its namenever knowing that you called it with a variable.

Quoting the $


You can prevent the shell from substituting the value of a variable by quoting the leading $. Double quotation marks do not prevent the substitution; single quotation marks or a backslash (\) do.

$ echo $person alex $ echo "$person" alex $ echo '$person' $person $ echo \$person $person


SPACEs


Because they do not prevent variable substitution but do turn off the special meanings of most other characters, double quotation marks are useful when you assign values to variables and when you use those values. To assign a value that contains SPACEs or TABs to a variable, use double quotation marks around the value. Although double quotation marks are not required in all cases, using them is a good habit.

$ person="alex and jenny" $ echo $person alex and jenny $ person=alex and jenny bash: and: command not found


When you reference a variable that contains TABs or multiple adjacent SPACEs, you need to use quotation marks to preserve the spacing. If you do not quote the variable, the shell collapses each string of blank characters into a single SPACE before passing the variable to the utility:

$ person="alex   and   jenny" $ echo $person alex and jenny $ echo "$person" alex   and   jenny


When you execute a command with a variable as an argument, the shell replaces the name of the variable with the value of the variable and passes that value to the program being executed. If the value of the variable contains a special character, such as * or ?, the shell may expand that variable.

Pathname expansion in assignments


The first line in the following sequence of commands assigns the string alex* to the variable memo. The Bourne Again Shell does not expand the string because bash does not perform pathname expansion (page 221) when assigning a value to a variable. All shells process a command line in a specific order. Within this order bash expands variables before it interprets commands. In the following echo command line, the double quotation marks quote the asterisk (*) in the expanded value of $memo and prevent bash from performing pathname expansion on the expanded memo variable before passing its value to the echo command:

$ memo=alex* $ echo "$memo" alex*


All shells interpret special characters as special when you reference a variable that contains an unquoted special character. In the following example, the shell expands the value of the memo variable because it is not quoted:

$ ls alex.report alex.summary $ echo $memo alex.report alex.summary


Here the shell expands the $memo variable to alex*, expands alex* to alex.report and alex.summary, and passes these two values to echo.

Optional

Braces


The $VARIABLE syntax is a special case of the more general syntax ${VARIABLE}, in which the variable name is enclosed by ${}. The braces insulate the variable name. Braces are necessary when catenating a variable value with a string:

$ PREF=counter $ WAY=$PREFclockwise $ FAKE=$PREFfeit $ echo $WAY $FAKE $


The preceding example does not work as planned. Only a blank line is output because, although the symbols PREFclockwise and PREFfeit are valid variable names, they are not set. By default bash evaluates an unset variable as an empty (null) string and displays this value. To achieve the intent of these statements, refer to the PREF variable using braces:

$ PREF=counter $ WAY=${PREF}clockwise $ FAKE=${PREF}feit $ echo $WAY $FAKE counterclockwise counterfeit


The Bourne Again Shell refers to the arguments on its command line by position, using the special variables $1, $2, $3, and so forth up to $9. If you wish to refer to arguments past the ninth argument, you must use braces: ${10}. The name of the command is held in $0 (page 921).


unset: Removes a Variable

Unless you remove a variable, it exists as long as the shell in which it was created exists. To remove the value of a variable but not the variable itself, set the value to null:

$ person= $ echo $person $


You can remove a variable with the unset builtin. To remove the variable person, give the following command:

$ unset person


Variable Attributes

This section discusses attributes and explains how to assign them to variables.

readonly: Makes the Value of a Variable Permanent

You can use the readonly builtin to ensure that the value of a variable cannot be changed. The next example declares the variable person to be readonly. You must assign a value to a variable before you declare it to be readonly; you cannot change its value after the declaration. When you attempt to unset or change the value of a readonly variable, the shell displays an error message:

$ person=jenny $ echo $person jenny $ readonly person $ person=helen bash: person: readonly variable


If you use the readonly builtin without an argument, it displays a list of all readonly shell variables. This list includes keyword variables that are automatically set as readonly as well as keyword or user-created variables that you have declared as readonly. See "Listing variable attributes" on page 290 for an example (readonly and declare r produce the same output).

declare and typeset: Assign Attributes to Variables

The declare and typeset builtins (two names for the same command) set attributes and values for shell variables. Table 9-3 lists five of these attributes.

Table 9-3. Variable attributes (typeset or declare)

Attribute

Meaning

-a

Declares a variable as an array (page 914)

-f

Declares a variable to be a function name (page 321)

-i

Declares a variable to be of type integer (page 291)

-r

Makes a variable readonly; also readonly (page 289)

-x

Exports a variable (makes it global); also export (page 916)


The following commands declare several variables and set some attributes. The first line declares person1 and assigns it a value of alex. This command has the same effect with or without the word declare.

$ declare person1=alex $ declare -r person2=jenny $ declare -rx person3=helen $ declare -x person4


The readonly and export builtins are synonyms for the commands declare r and declare x, respectively. It is legal to declare a variable without assigning a value to it, as the preceding declaration of the variable person4 illustrates. This declaration makes person4 available to all subshells (makes it global). Until an assignment is made to the variable, it has a null value.

You can list the options to declare separately in any order. The following is equivalent to the preceding declaration of person3:

$ declare -x -r person3=helen


Use the + character in place of when you want to remove an attribute from a variable. You cannot remove a readonly attribute however. After the following command is given, the variable person3 is no longer exported but it is still readonly.

$ declare +x person3


You can also use typeset instead of declare.

Listing variable attributes


Without any arguments or options, the declare builtin lists all shell variables. The same list is output when you run set (page 924) without any arguments.

If you use a declare builtin with options but no variable names as arguments, the command lists all shell variables that have the indicated attributes set. For example, the option r with declare gives a list of all readonly shell variables. This list is the same as that produced by a readonly command without any arguments. After the declarations in the preceding example have been given, the results are as follows:

$ declare -r declare -ar BASH_VERSINFO='([0]="2" [1]="05b" [2]="0" [3]="1" ... )' declare -ir EU declare -ir PP declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:..." declare -ir U declare -r person2="jenny" declare -rx person3="helen"


The first five entries are keyword variables that are automatically declared as read-only. Some of these variables are stored as integers (i). The a option indicates that BASH_VERSINFO is an array variable; the value of each element of the array is listed to the right of an equal sign.

Integer


By default the values of variables are stored as strings. When you perform arithmetic on a string variable, the shell converts the variable into a number, manipulates it, and then converts it back to a string. A variable with the integer attribute is stored as an integer. Assign the integer attribute as follows:

$ typeset -i COUNT


Keyword Variables

Keyword variables either are inherited or are declared and initialized by the shell when it starts. You can assign values to these variables from the command line or from a startup file. Typically you want these variables to apply to all subshells you start as well as to your login shell. For those variables not automatically exported by the shell, you must use export (page 916) to make them available to child shells.

HOME: Your Home Directory

By default your home directory is your working directory when you log in. Your home directory is determined when you establish your account; its name is stored in the /etc/passwd file.

$ grep sam /etc/passwd sam:x:501:501:Sam S. x301:/home/sam:/bin/bash


When you log in, the shell inherits the pathname of your home directory and assigns it to the variable HOME. When you give a cd command without an argument, cd makes the directory whose name is stored in HOME the working directory:

$ pwd /home/alex/laptop $ echo $HOME /home/alex $ cd $ pwd /home/alex


This example shows the value of the HOME variable and the effect of the cd builtin. After you execute cd without an argument, the pathname of the working directory is the same as the value of HOME: your home directory.

Tilde (~)


The shell uses the value of HOME to expand pathnames that use the shorthand tilde (~) notation (page 171) to denote a user's home directory. The following example uses echo to display the value of this shortcut and then uses ls to list the files in Alex's laptop directory, which is a subdirectory of his home directory:

$ echo ~ /home/alex $ ls ~/laptop tester     count      lineup


PATH: Where the Shell Looks for Programs

When you give the shell an absolute or relative pathname rather than a simple filename as a command, it looks in the specified directory for an executable file with the specified filename. If the file with the pathname you specified does not exist, the shell reports command not found. If the file exists as specified but you do not have execute permission for it, or in the case of a shell script you do not have read and execute permission for it, the shell reports Permission denied.

If you give a simple filename as a command, the shell searches through certain directories for the program you want to execute. It looks in several directories for a file that has the same name as the command and that you have execute permission for (a compiled program) or read and execute permission for (a shell script). The PATH shell variable controls this search.

The default value of PATH is determined when bash is compiled. It is not set in a startup file, although it may be modified there. Normally the default specifies that the shell search several system directories used to hold common commands and then search the working directory. These system directories include /bin and /usr/bin and other directories appropriate to the local system. When you give a command, if the shell does not find the executableand, in the case of a shell script, readablefile named by the command in any of the directories listed in PATH, the shell generates one of the aforementioned error messages.

Working directory


The PATH variable specifies the directories in the order the shell should search them. Each directory must be separated from the next by a colon. The following command sets PATH so that a search for an executable file starts with the /usr/local/bin direc-tory. If it does not find the file in this directory, the shell first looks in /bin, and then in /usr/bin. If the search fails in those directories, the shell looks in the bin directory, a subdirectory of the user's home directory. Finally the shell looks in the working directory. Exporting PATH makes its value accessible to subshells:

$ export PATH=/usr/local/bin:/bin:/usr/bin:~/bin:


A null value in the string indicates the working directory. In the preceding example, a null value (nothing between the colon and the end of the line) appears as the last element of the string. The working directory is represented by a leading colon (not recommended; see the following security tip), a trailing colon (as in the example), or two colons next to each other anywhere in the string. You can also represent the working directory explicitly with a period (.).

Because Linux stores many executable files in directories named bin (binary), users typically put their own executable files in their own ~/bin directories. If you put your own bin directory at the end of your PATH, as in the preceding example, the shell looks there for any commands that it cannot find in directories listed earlier in PATH.

Security: PATH and security

Do not put the working directory first in PATH when security is a concern. If you are running as Superuser, you should never put the working directory first in PATH. It is common for Superuser PATH to omit the working directory entirely. You can always execute a file in the working directory by prepending ./ to the name: ./ls.

Putting the working directory first in PATH can create a security hole. Most people type ls as the first command when entering a directory. If the owner of a directory places an executable file named ls in the directory, and the working directory appears first in a user's PATH, the user giving an ls command from the directory executes the ls program in the working directory instead of the system ls utility, possibly with undesirable results.


If you want to add directories to PATH, you can reference the old value of the PATH variable while you are setting PATH to a new value (but see the preceding security tip). The following command adds /usr/local/bin to the beginning of the current PATH and the bin directory in the user's home directory (~/bin) to the end:

$ PATH=/usr/local/bin:$PATH:~/bin


MAIL: Where Your Mail Is Kept

The MAIL variable contains the pathname of the file that holds your mail (your mailbox, usually /var/spool/mail/name, where name is your username). If MAIL is set and MAILPATH (next) is not set, the shell informs you when mail arrives in the file specified by MAIL. In a graphical environment you can unset MAIL so that the shell does not display mail reminders in a terminal emulator window (assuming you are using a graphical mail program).

The MAILPATH variable contains a list of filenames separated by colons. If this variable is set, the shell informs you when any one of the files is modified (for example, when mail arrives). You can follow any of the filenames in the list with a question mark (?), followed by a message. The message replaces the you have mail message when you get mail while you are logged in.

The MAILCHECK variable specifies how often, in seconds, the shell checks for new mail. The default is 60 seconds. If you set this variable to zero, the shell checks before each prompt.

PS1: User Prompt (Primary)

The default Bourne Again Shell prompt is a dollar sign ($). When you run bash as root, you may have a pound sign (#) prompt. The PS1 variable holds the prompt string that the shell uses to let you know that it is waiting for a command. When you change the value of PS1, you change the appearance of your prompt.

You can customize the prompt displayed by PS1. For example, the assignment

$ PS1="[\u@\h \W \!]$ "


displays the following prompt:


[user@host directory event]$

where user is the username, host is the hostname up to the first period, directory is the basename of the working directory, and event is the event number of the current command.

If you are working on more than one system, it can be helpful to incorporate the system name into your prompt. For example, you might change the prompt to the name of the system you are using, followed by a colon and a SPACE (a SPACE at the end of the prompt makes the commands that you enter after the prompt easier to read):

$ PS1="$(hostname): " bravo.example.com: echo test test bravo.example.com:


The first example that follows changes the prompt to the name of the local host, a SPACE, and a dollar sign (or, if the user is running as root, a pound sign). The second example changes the prompt to the time followed by the name of the user. The third example changes the prompt to the one used in this book (a pound sign for root and a dollar sign otherwise):

$ PS1='\h \$ ' bravo $ $ PS1='\@ \u $ ' 09:44 PM alex $ $ PS1='\$ ' $


Table 9-4 describes some of the symbols you can use in PS1. For a complete list of special characters you can use in the prompt strings, open the bash man page and search for the second occurrence of PROMPTING (give the command /PROMPTING and then press n).

Table 9-4. PS1 symbols

Symbol

Display in prompt

\$

# if the user is running as root; otherwise, $

\w

Pathname of the working directory

\W

Basename of the working directory

\!

Current event (history) number (page 307)

\d

Date in Weekday Month Date format

\h

Machine hostname, without the domain

\H

Full machine hostname, including the domain

\u

Username of the current user

\@

Current time of day in 12-hour, AM/PM format

\T

Current time of day in 12-hour HH:MM:SS format

\A

Current time of day in 24-hour HH:MM format

\t

Current time of day in 24-hour HH:MM:SS format


PS2: User Prompt (Secondary)

Prompt String 2 is a secondary prompt that the shell stores in PS2. On the first line of the next example, an unclosed quoted string follows echo. The shell assumes that the command is not finished and, on the second line, gives the default secondary prompt (>). This prompt indicates that the shell is waiting for the user to continue the command line. The shell waits until it receives the quotation mark that closes the string and then executes the command:

$ echo "demonstration of prompt string > 2" demonstration of prompt string 2 $ PS2="secondary prompt: " $ echo "this demonstrates secondary prompt: prompt string 2" this demonstrates prompt string 2


The second command changes the secondary prompt to secondary prompt: followed by a SPACE. A multiline echo demonstrates the new prompt.

PS3: Menu Prompt

PS3 holds the menu prompt for the select control structure (page 908).

PS4: Debugging Prompt

PS4 holds the bash debugging symbol (page 890).

IFS: Separates Input Fields (Word Splitting)

The IFS (Internal Field Separator) shell variable specifies the characters that you can use to separate arguments on a command line and has the default value of SPACE TAB NEWLINE. Regardless of the value of IFS, you can always use one or more SPACE or TAB characters to separate arguments on the command line, provided that these characters are not quoted or escaped. When you assign IFS character values, these characters can also separate fields but only if they undergo expansion. This type of interpretation of the command line is called word splitting.

Caution: Be careful when changing IFS

Changing IFS has a variety of side effects so work cautiously. You may find it useful to first save the value of IFS before changing it; you can easily then restore the original value if you get unexpected results. Alternatively, you can fork a new shell with a bash command before experimenting with IFS; if you get into trouble, you can exit back to the old shell, where IFS is working properly. You can also set IFS to its default value with the following command:

$ IFS=' \t\n'



The following example demonstrates how setting IFS can affect the interpretation of a command line:

$ a=w:x:y:z $ cat $a cat: w:x:y:z: No such file or directory $ IFS=":" $ cat $a cat: w: No such file or directory cat: x: No such file or directory cat: y: No such file or directory cat: z: No such file or directory


The first time cat is called, the shell expands the variable a, interpreting the string w:x:y:z as a single word to be used as the argument to cat. The cat utility cannot find a file named w:x:y:z and reports an error for that filename. After IFS is set to a colon (:), the shell expands the variable a into four words, each of which is an argument to cat. Now cat reports an error for four separate files: w, x, y, and z. Word splitting based on the colon (:) takes place only after the variable a is expanded.

The shell splits all expanded words on a command line according to the separating characters found in IFS. When there is no expansion, there is no splitting. Consider the following commands:

$ IFS="p" $ export VAR


Although IFS is set to p, the p on the export command line is not expanded so the word export is not split.

The following example uses variable expansion in an attempt to produce an export command:

$ IFS="p" $ aa=export $ echo $aa ex ort


This time expansion occurs so that the character p in the token export is interpreted as a separator as the preceding echo command shows. Now when you try to use the value of the aa variable to export the VAR variable, the shell parses the $aa VAR command line as ex ort VAR. The effect is that the command line starts the ex editor with two filenames: ort and VAR.

$ $aa VAR 2 files to edit "ort" [New File] Entering Ex mode.  Type "visual" to go to Normal mode. :q E173: 1 more file to edit :q $


If you unset IFS, only SPACEs and TABs work as field separators.

Tip: Multiple separator characters

Although sequences of multiple SPACE or TAB characters are treated as single separators, each occurrence of another field-separator character acts as a separator.


CDPATH: Broadens the Scope of cd

The CDPATH variable allows you to use a simple filename as an argument to the cd builtin to change the working directory to a directory other than a child of the working directory. If you have several directories you like to work out of, this variable can speed things up and save you the tedium of using cd with longer pathnames to switch among them.

When CDPATH is not set and you specify a simple filename as an argument to cd, cd searches the working directory for a subdirectory with the same name as the argument. If the subdirectory does not exist, cd displays an error message. When CDPATH is set, cd searches for an appropriately named subdirectory in the directories in the CDPATH list. If cd finds one, that directory becomes the working directory. With CDPATH set, you can use cd and a simple filename to change the working directory to a child of any of the directories listed in CDPATH.

The CDPATH variable takes on the value of a colon-separated list of directory pathnames (similar to the PATH variable). It is usually set in the ~/.bash_profile startup file with a command line such as the following:

export CDPATH=$HOME:$HOME/literature


This command causes cd to search your home directory, the literature directory, and then the working directory when you give a cd command. If you do not include the working directory in CDPATH, cd searches the working directory if the search of all the other directories in CDPATH fails. If you want cd to search the working directory first (which you should never do when you are logged in as rootrefer to the tip on page 293), include a null string, represented by two colons (::), as the first entry in CDPATH:

export CDPATH=::$HOME:$HOME/literature


If the argument to the cd builtin is an absolute pathnameone starting with a slash (/)the shell does not consult CDPATH.

Keyword Variables: A Summary

Table 9-5 lists the bash keyword variables.

Table 9-5. bash keyword variables

Variable

Value

BASH_ENV

The pathname of the startup file for noninteractive shells (page 268)

CDPATH

The cd search path (page 297)

COLUMNS

The width of the display used by select (page 907)

FCEDIT

The name of the editor that fc uses by default (page 305)

HISTFILE

The pathname of the file that holds the history list (default: ~/.bash_history; page 302)

HISTFILESIZE

The maximum number of entries saved in HISTFILE (default: 500; page 302)

HISTSIZE

The maximum number of entries saved in the history list (default: 500; page 302)

HOME

The pathname of the user's home directory (page 291); used as the default argument for cd and in tilde expansion (page 171)

IFS

Internal Field Separator (page 295); used for word splitting (page 335)

INPUTRC

The pathname of the Readline startup file (default: ~/.inputrc; page 315)

LANG

The locale category when that category is not specifically set with an LC_* variable

LC_*

A group of variables that specify locale categories including LC_COLLATE, LC_CTYPE, LC_MESSAGES, and LC_NUMERIC; use the locale builtin to display a complete list with values

LINES

The height of the display used by select (page 907)

MAIL

The pathname of the file that holds a user's mail (page 293)

MAILCHECK

How often, in seconds, bash checks for mail (page 293)

MAILPATH

A colon-separated list of file pathnames that bash checks for mail in (page 293)

PATH

A colon-separated list of directory pathnames that bash looks for commands in (page 292)

PROMPT_COMMAND

A command that bash executes just before it displays the primary prompt

PS1

Prompt String 1; the primary prompt (default: '\s-\v\$ '; page 293)

PS2

Prompt String 2; the secondary prompt (default: '> '; page 295)

PS3

The prompt issued by select (page 907)

PS4

The bash debugging symbol (page 890)

REPLY

Holds the line that read accepts (page 928); also used by select (page 907)





A Practical Guide to Red Hat Linux
A Practical Guide to Red HatВ® LinuxВ®: Fedoraв„ў Core and Red Hat Enterprise Linux (3rd Edition)
ISBN: 0132280272
EAN: 2147483647
Year: 2006
Pages: 383

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