To set a shell variable, type the variable name, an equal sign, and the value you wish to assign (all values are treated as text):
$ A=red
Once a variable has been assigned a value, you can use it in commands, preceded by a dollar sign:
$ ls -lred
ls: red: No such file or directory
$ touch $A
$ ls -l red
-rw-r--r-- 1 hank hank 0 Jul 18 15:26 red
The echo command can be used to view the value of a variable:
$ echo $A
red
To destroy a variable, use the unset command:
$ echo $A
red
$ unset A
$ echo $A
$
Finally, to make a variable accessible to processes started by the current process, use the export command:
$ unset A
$ TEST=blue
$ echo $TEST # variable is known to the shell
blue
$ bash # start a child shell
[hank@beige foo]$ echo $TEST # variable is not known to child
[hank@beige foo]$ exit # exit back to parent shell
exit
$ export TEST # export the variable
$ echo $TEST # value is still known to the shell
blue
$ bash # start a new child shell
[hank@beige foo]$ echo $TEST # exported value is known to the child
blue
The PATH value is stored in an environment variable of the same name. Its value can be viewed like any other environment variable:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin
To add a directory to the existing directories, use $PATH on the righthand side of an assignment to insert the current value of the variable into the new value:
$ PATH=$PATH:/home/hank/bin
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/hank/bin
You don't need to export PATH in this case because it has already been exported; assigning a new value does not changes its exported status.topten /home/hank/bin
$ topten
-rw-r--r-- 1 root root 807103 Jul 12 21:18 termcap
-rw-r--r-- 1 root root 499861 Jul 17 08:08 prelink.cache
-rw-r--r-- 1 root root 362031 Feb 23 08:09 services
-rw-r--r-- 1 root root 97966 Jul 15 11:19 ld.so.cache
-rw-r--r-- 1 root root 92794 Jul 12 12:46 Muttrc
-rw-r--r-- 1 root root 83607 Mar 23 07:23 readahead.files
-rw-r--r-- 1 root root 73946 Jul 13 02:23 sensors.conf
-rw-r--r-- 1 root root 45083 Jul 12 18:33 php.ini
-rw-r--r-- 1 root root 30460 Jul 13 20:36 jwhois.conf
-rw-r--r-- 1 root root 26137 Mar 23 07:23 readahead.early.files
Within a script, you can prompt the user using the echo command, and then use the read command to read a line from the user and place it in an environment variable:
echo "Please enter your name:"
read NAME
echo "Hello $NAME!"
Or you can collect the standard output of a command and assign it to a variable using the $( ) symbols:
$ NOW=$(date)
$ echo $NOW
Tue Jul 18 22:25:48 EDT 2006
4.12.1.2. Special variables
special parameters special variables bashTable 4-17. Important special variables
| Name | Description | Notes |
|---|---|---|
| $$ | Process ID of the shell | Since process IDs are unique (at any one point in time), this can be used to ensure unique filenames (e.g., /tmp/$$.txt will never conflict with the same filename used by another copy of the same script). |
| $0 | Name of the script | Useful to generate error messages, and when one script is invoked through more than one name. |
| $1, $2, $3, ... | Arguments given on the script's command line | The shift command will eliminate $1 and then shift all of the parameters accordingly ($2 becomes $1, $3 becomes $2, and so forth). |
| $# | Number of arguments from the script's command line | If $# is 0, then no options were given on the command line. |
| $* $@ | All of the arguments from the script's command line | When quoted, "$*" becomes a single block of text containing all of the arguments, while "$@" becomes separate words. If the script is called with the arguments "green" and "yellow", then "$*" would evaluate to "green yellow", while "$@" would evaluate to "green" "yellow". |
| $? | Exit status of the last command | Manpages document the possible exit-status values for most commands. |
4.12.1.3. Control structures
bashTable 4-18. Common bash control structures
| Structure | Notes | Example |
|---|---|---|
| for variable in list | The variable is assigned the first value in list , and loop-commands are executed. The process is then repeated for all of the other values in list . | # Set X to 'hosts', then display the filename and file contents. Repeat for 'services' |
| do | for X in hosts services | |
| loop-commands | do | |
| done | echo "==== $X" | |
| cat /etc/$X | ||
| done | ||
| if control-command | If the control-command succeeds, the if-commands are executed; otherwise, the else-commands are executed. | # Tell the user if the text 'test' appears in file1 |
| then | if grep -q test file1 | |
| if-commands | then | |
| [else | echo "Found it!" | |
| else-commands ] | else | |
| fi | echo "Not found." | |
| fi | ||
| while control-command | As long as control-command executes successfully, loop-commands are repeated. | # Display the free disk space every 2 seconds, forever |
| do | while sleep 2 | |
| loop-commands | do | |
| done | df -h | |
| done |
The for..in control structure is great for looping over a range of values. This loop will display the status of the httpd , ftpd , and NetworkManager services:
for SERVICE in httpd ftpd NetworkManager
do
/sbin/service $SERVICE status
done
for...in is even more useful when the list of values is specified as an ambiguous filename. In this script, the loop is repeated once for each file in the directory /etc/ that ends in .conf :