May the source be with you, but remember the KISS principle ;-)

Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Bash Variables


Bash Recommended Links BASH Debugging Command history reuse Advanced filesystem navigation

Command completion

 IFS Dotfiles  Shell Prompts Bash tips Annotated List of Bash Enhancements Humor Etv

By default, bash variables are untyped and can be used both for arithmetic operations and string parsing. They can be global (external), local to the shell instance and local to the function and built-in. 

Access can be read-write or read-only.

Variables in  bash can be classified into two group:

Use the set command to see the value of all variables and function definitions in the current shell.

Use the env (or export -p) command to see only those variables that have been exported and would be available to a subshell.

In bash version 4 or newer, you can also use the declare -p command.

Predefined system variables

There are many system variables that are defined in bash. Among them:

Environment variable Use
BASH_VERSION The version of the current Bash session
HOME The home directory of the current user
HOSTNAME The name of the host
LANG The locale used to manage the data
PATH The search path for the shell
PS1 The prompt configuration
PWD The path to the current directory
USER The name of the currently logged in user
LOGNAME Same as user

For us two variables are of primary important: PATH and LD_LIBRARY_PATH

Both define set of directories that can be accesses by bash when loadling the program ($PATH) or loading a library (LD_LIBRARY_PATH).  Most Linux distributions include the following directories:


PATH Variable

There are multiple system variable in shell, the variables that are set by the system.

For example, PATH variable.  Of couse you cal also set it yourself:


assigns the value


 to the shell variable named PATH. Shell variables are typeless and can have both athithmentic and non-numeric values.

Shell variables are widely used within shell scripts, because they provide a convenient way of transferring values from one command to another. Programs can obtain the value of a shell variable and use the value to modify their operation, in much the same way they use the value of command-line arguments.

You can see a list of system variables in you env by issuing the env command. Usually, the command produces more than a single screen of output. So, you can use a pipe redirector and the more  command to view the output one screen at a time:

env | more

Press the Space bar to see each successive page of output. You'll probably see several of the shell variables described below:

You can use the value of a shell variable in a command by preceding the name of the shell variable by a dollar sign ($). To avoid confusion with surrounding text, you can enclose the name of the shell variable within curly braces ({});  For example, you can change the current working directory to your home directory by issuing the command:

cd $HOME

An easy way to see the value of a shell variable is to specify the variable as the argument of the echo  command. For example, to see the value of the PATH shell variable, issue the command:

echo $PATH

To make the value of a shell variable available not just to the shell, but to programs invoked by using the shell, you must export the shell variable. To do so, use the export  command, which has the form:

export variable

where variable specifies the name of the variable to be exported. A shorthand form of the command lets you assign a value to a shell variable and export the variable in a single command:

export variable=value

You can remove the value associated with shell variable by giving the variable an empty value:


However, a shell variable with an empty value remains a shell variable and appears in the output of the set  command. To dispense with a shell variable, you can issue the unset  command:

unset variable

Once you unset the value of a variable, the variable no longer appears in the output of the set  command.

The Search Path

The special shell variable PATH holds a series of paths known collectively as the search path. Whenever you issue an external command, the shell searches paths that comprise the search path, seeking the program file that corresponds to the command. The startup scripts establish the initial value of the PATH shell variable, but you can modify its value to include any desired series of paths. You must use a colon (:) to separate each path of the search path.

For example, suppose that PATH has the following value:


You can add a new search directory, say /opt/bin, with the following command:


Now, the shell will look for external programs in /opt/bin/ as well as the default directories. However, it will look there last. If you prefer to check /opt/bin first, issue the following command instead:


The which command helps you work with the PATH shell variable. It checks the search path for the file specified as its argument and prints the name of the matching path, if any. For example, suppose you want to know where the program file for the wc  command resides. Issuing the command:

which wc

will tell you that the program file is /usr/bin/wc, or whatever other path is correct for your system.


Variable Basics

Variables are declared using the Bash declare command. To declare a variable named COST, use this:

$ declare COST

Use the built-in typeset statement for compatibility with the Korn shell. If you are using Bash, use declare instead. declare has all the features of the older typeset command.

Choosing good variable names is important. One time, when I was grading a first-year computer science assignment, a student used 26 variables named A to Z. There was no explanation about what the variables represented and it took me half an hour to determine whether the program actually worked. (Surprisingly, it did.)

Names should also be consistent. In the mutual fund industry, for example, “portfolios,” “accounts,” and “funds” often mean the same thing. It is better to use one of these three names throughout your script. If three different terms are used, the reader might assume there are subtle differences in meaning between them.

Because Bash does minimum checking of variable names, even with the nounset option turned on, another common mistake is using a variable that looks the same. In my first year in university, I ran into an old friend who was frustrated because his Fortran program wasn't working. When I examined it closely, I saw that he had declared a variable called HIGH, but in the body of his program he spelled the variable HI. When the program printed the value of HIGH, it was zero because it was never actually assigned a value. The same kind of situation can occur in Bash scripts.

Variable names begin with a leading alphabetic or underscore character followed by additional alphanumeric characters or underscores.

Although variables can be in upper- or lowercase, tradition dictates variables are named in uppercase so as not to be confused with shell commands, which are almost always in lowercase. TOTAL, ORDERS_EUROPE, and _W3C are all legitimate variable names. There are no reserved words, which are words that are reserved for a specific purpose in the shell.

Variables are assigned new values with an equals sign (=). To assign an empty string to a variable, don't supply any value.


Otherwise, include some text to be assigned.

$ COST=0

Although printf %d prints a zero for both a value of zero and an empty string, Bash considers the two values to be different. A variable with no value is not the same as a variable with a value of zero.

Values can also be assigned with the let statement described in Chapter 6.

Bash differentiates between a variable's name and the value the variable represents. To refer to the value of a variable, you must precede the name with a dollar sign ($).

$ printf "%s" $COST


The dollar sign means “substitute.” The shell replaces $COST with the value COST represents. In this case, the value of COST is zero. After substituting the value of COST, the command becomes:

$ printf "%d" 0


Bash executes this command and displays a zero.

Values can be assigned an initial value when the variable is first declared.

$ declare COST=5
$ printf "%d" $COST


Because declare is a command, variables are created only when the declare command is executed. They remain in existence until the script ends or until the variable is destroyed with the built-in unset command.

$ unset COST


The unset command is a command-line convenience. In well-structured scripts, variables are declared at the start of a script and are not unset. This prevents confusion because the programmer can be sure that the variables always exist while the script is running.

The results of a command can also be assigned to a variable. If a command is contained in backquotes ('), everything written to standard output is stored in the variable being assigned instead.

$ NUMBER_OF_FILES='ls -1 | wc -l'
$ printf "%d" "$NUMBER_OF_FILES"

Default values

We just saw the simplest among different ways to manipulate the value held by a variable. What we are going to see now is how to thinker with a variable to have default values and messages, so we make the interaction with the variable more flexible. Before proceeding, just bear in mind that we can use two notations for our next example and they are equivalent:

So, you could see either of the two in a script, and both are correct:

${variable:-default} ${variable-default}  

Simply, if a variable is not set, return a default value, as we can see in the following example:

echo "Setting the variable x"
echo "Printing the value of x using a default fallback value"
echo "${x:-20}"
echo "Unsetting x"
unset -v x
echo "Printing the value of x using a default fallback value"
echo "${x:-20}"
echo "Setting the value of x to null"
echo "Printing the value of x with x to null"
echo "${x:-30}  

Now, let's execute it:

zarrelli:~$ ./ 
Setting the variable x
Printing the value of x using a default fallback value
Unsetting x
Printing the value of x using a default fallback value
Setting the value of x to null
Printing the value of x with x to null

As mentioned before, the two notations, with or without the colon, are quite the same. Let us see what happens if in the previous script we substitute ${x:-somenumber} with ${x-somenumber}.

Let's run the modified script:

Setting the variable x
Printing the value of x using a default fallback value
Unsetting x
Printing the value of x using a default fallback value
Setting the value of x to null
Printing the value of x with x to null    

Everything is fine, but the last line. So what is the difference at play here? Simple:

  • *${x-30}: The notation with a colon forces a check on the existence of a value for the variable and this value may well be null. In case you have a value, it does print the value of the variable, ignoring the fallback.
    • unset -f x: It unsets the variable, so it has no value and we have a fallback value
    • x=: It gives a null to x; so the fallback does not come in to play, and we get back the variable value, for example, null
  • ${x:-30}: This forces a fallback value in case the value of a variable is null or nonexistent
    • unset -f x: It unsets the variable, so it has no value and we have a fallback value
    • x=: It gives a null to x, but the fallback comes in to play and we get a default value

\Variable Attributes

All Bash variables are stored as simple strings. Each variable has certain options called attributes, which can be turned on or off by using the declare command in a similar way to shell options and the shopt command.

If a variable is declared with the -i (integer) switch, Bash turns on the integer attribute for that variable. The shell will remember that the string should be treated as an integer value. If a non-numeric value is assigned to an integer variable, Bash does not report an error but instead assigns a value of zero.

$ declare -i NUMBER_ACCOUNTS=15
$ printf "%d\n" "$NUMBER_ACCOUNTS"
$ NUMBER_ACCOUNTS="Smith" # mistake
$ printf "%d\n" "$NUMBER_ACCOUNTS"
$ printf "%d\n" "$NUMBER_ACCOUNTS"


Sometimes an attempt to assign a string produces an error, but you can't rely on this behavior.

$ NUMBER_ACCOUNTS="Smith Account" # mistake
bash: Smith Account: syntax error in expression (error token is "Account")


The attributes of a variable can be displayed with the -p (print) switch.

$ declare -p NUMBER_ACCOUNTS
declare -i NUMBER_ACCOUNTS="12"


The information is displayed in such a way that it can be saved for use in another script. This allows you to experiment with declarations at the command prompt and then write the declarations to a script file when you are satisfied with the results.

The integer attribute can be turned off with a plus sign.

$ declare +i NUMBER_ACCOUNTS # turn off integer attribute
$ printf "%d\n" "$NUMBER_ACCOUNTS"
bash: printf: Smith Account: invalid number
$ printf "%s\n" "$NUMBER_ACCOUNTS"
Smith Account


Although Bash does not consider the assignment of a non-numeric value an error, the printf command does report that the value can't be formatted as a number.

Like the printf command, integer variables can be assigned octal or hexadecimal numbers as well.

$ declare -i NUMBER_ACCOUNTS=0X0F
$ printf "%i\n" "$NUMBER_ACCOUNTS"


Constants are unchanging variables that are created with the -r (read-only) attribute. If you attempt to assign a value to a constant, Bash reports an error. Suppose the constant COMPANY has the name of a company.

$ declare -r COMPANY="Smith and Jones"
$ printf "%s\n" "$COMPANY"
Smith and Jones
$ COMPANY="Wilson Distribution"
bash: COMPANY: readonly variable


The readonly attribute can be turned off using a plus sign. However, this can make your scripts confusing to read because the reader will assume that a readonly variable is always read-only. Either remove the readonly attribute or change the structure of the script.


Predefined Variables

Bash has more than 50 predefined variables. These variables, created when Bash is first started, provide information about the Bash session and can be used to control some of the shell's features.

Some of these variables have special properties that might be lost if you unset the variable and then create a new one with the same name. For example, the variable RANDOM contains a random number. If you delete RANDOM with unset and declare a new variable called RANDOM, this new variable is a normal shell variable and does not contain random numbers. Therefore, it's best to avoid creating variables with the same name as the predefined variables.

The declare command, with no switches, lists all currently defined values.

  • BASH— The full pathname of Bash.

  • BASH_ENV— In a shell script, the name of the profile file executed before the script was started.

  • BASH_VERSION— The version of Bash (for example, 2.04.0(1)-release).

  • COLUMNS— The number of characters per line on your display (for example, 80).

  • FUNCNAME— If inside a function, the name of the function.

  • HOSTNAME— The name of the computer. Under some versions of Linux, this can be the machine name. On others, it can be a fully qualified domain name.

  • HOSTTYPE— Type of computer.

  • HOME— The name of your home directory.

  • IFS— The internal field separator, a list of characters used to split a line into shell words.

  • LINENO— The current line number in a script or function.

  • LINES— The number of horizontal lines in your display (for example, 24).

  • OSTYPE— The name of the operating system.

  • PATH— Colon-separated list of search paths to find a command to execute.

  • PPID— The process ID of the shell's parent process.

  • PROMPT_COMMAND— Command to execute before the setting of the PS1 primary prompt string.

  • PS1— The primary prompt string.

  • PS2— The secondary prompt string.

  • PS3— The select command prompt string.

  • PS4— The trace command output prefix string.

  • PWD— The current working directory (as set by the cd command).

  • RANDOM— Returns a random number between 0 and 32767 each time it is referenced.

  • SHELL— The preferred shell to use; for programs that start a shell for you.

  • TERM— The terminal emulation type (for example, console).

Linux distributions define additional variables. The presence of these variables depends on your particular distribution. Many are declared for the use of applications.

  • DISPLAY is the X Window display server.

  • EDITOR is your default editor. Historically, this was used to indicate a line editor to use when a visual editor was not available (see VISUAL).

  • ORGANIZATION is the name of your organization (usually the contents of /etc/organization).

  • TERM is the terminal emulation (for example, xterm for an xterm session, or linux for the Linux console).

  • VISUAL is your default editor, usually the same as EDITOR.

  • WINDOWMANAGER is the path to your current X Windows window manager.

A complete list appears in the reference section at the end of this chapter.

The Effect of Quotations

Those people familiar with other computer languages might be confused by the way Bash uses quotation marks. Single and double quotes are not used to delineate strings or characters, but to control how the shell groups characters and interprets special characters within a string. Bash calls this process word splitting.

$ COST=0
$ COST="0"


These two assignments produce the same result: COST is assigned a value of 0. The double quotes explicitly show that the value to assign to COST includes the character zero. Short alphanumeric values can be assigned to variables without quotations. However, when the string contains spaces, it's no longer apparent what value is to be assigned. Consider the following example.

$ DISTRIBUTION_CENTERS=London ; Paris ; New York
bash: Paris: command not found
bash: New: command not found


When Bash examines the second assignment statement, it sees a value of London terminated by a space. It assigns that value to the variable. It then sees the semicolon, the command separator, and expects a new statement to follow. It tries to execute the Paris command (there is none). It tries to do the same with the New command, giving it the York argument.

For this reason, it is a safe practice to enclose all assignment values in double quotation marks. Even if your company only has a distribution center in London, there's always the chance that a new distribution center will be added to the string, causing the shell script to crash. Always enclosing values in quotes ensures that Bash knows exactly what value is to be assigned.

$ DISTRIBUTION_CENTERS="London ; Paris ; New York"


The results are still not correct. Bash took the DISTRIBUTION_CENTERS value and removed the spaces so that printf doesn't interpret it as separate arguments of London, ;, Paris, ;, New, and York. The printf argument must also be enclosed in double quotes to keep the value of the variable as a single argument with the spacing intact.

London ; Paris ; New York


Again, it is a safe practice to always enclose variable substitutions with quotes.

Because the quotation marks are not delimiters but hints on how to interpret special characters, they can be used back-to-back. This is a convenient way to separate variables from the surrounding text in a string.

$ TAX=7.25
$ TAX_MESSAGE="The tax is ""$TAX""%"
$ printf "%s" "$TAX_MESSAGE"
The tax is 7.25%


Separating each of the quoted pieces with a space would result in the same problem you saw previously: Bash would treat them as three individual values.

Alternatively, a variable substitution's variable name can be enclosed in curly braces to make it clear where the variable's name begins and ends.

$ TAX_MESSAGE="The tax is ${TAX}%"


Besides space interpretation, another effect of quotation marks is that no pattern matching is done. Normally, for example, the asterisk (*) represents all the files in the current directory. Quotation marks prevent the asterisk from being replaced with a list of files.

$ printf "%s\n" *
$ printf "%s\n" "*"


To print strings without interpreting the special characters inside, use single quotes. Double quotes do not prevent Bash from interpreting the special characters $, ', and \, but single quotes leave all characters unchanged.

$ printf "%s" '$TAX_MESSAGE'


In this case, the single quotes prevent Bash from interpreting the value as a variable substitution because the dollar sign is not treated specially.

The backslash (\) acts like single quotes for one character, leaving the character unchanged. For example, to print a double quote mark, do this:

$ printf "%s" "\""


The backslash indicates that the second quote mark is to be treated as a character, not as the ending quote of a pair of quote marks.

The printf formatting code %q (quoting) prints backslashes before every character that has a special meaning to the shell. Use this to ensure that spacing is left intact.

$ printf "%q" "$TAX_MESSAGE"
The\ tax\ is\ 7.25%


For example, reading from files is affected by %q. If the printed variables contain spaces, read treats the spaces as separators unless they are protected with backslashes.

$ printf "%q %q\n" "Alpha Systems Inc" "Key West, Florida" > company.txt
$ read COMPANY LOCATION < company.txt
$ printf "%s\n" "$COMPANY"
Alpha Systems Inc
$ printf "%s %s\n" "Alpha Systems Inc" "Key West, Florida" > company.txt
$ read COMPANY LOCATION < company.txt
$ printf "%s\n" "$COMPANY"


The read command has no knowledge of what text on the line belonged originally to which variable. It assumes that the values are separated by spaces and assigns Alpha to COMPANY. When %q is used, read knows that the backslash protected spaces belong with the first value and it reads everything up to the first unprotected space, assigning Alpha Systems Inc to COMPANY.

Word splitting is controlled by the value of the special variable IFS. Normally, IFS treats spaces, tabs, and newline characters as word delimiters—that is, it uses whitespace characters. If the content of IFS is changed, the new characters are used as word delimiters. However, this is an older feature for compatibility with the Bourne shell and the IFS variable should not be altered by scripts because newer features such as %q formatting are available.

Whenever values are assigned or are substituted with a dollar sign, it is good practice to always enclose the values in double quotes to prevent problems with values containing spaces.


Arrays are lists of values that are created with the -a (array) attribute. A number called an index refers to the position item in the array. Bash arrays differ from arrays in other computer languages because they are open-ended. Arrays can be any length and are initially filled with empty strings for items.

$ declare -a PRODUCTS


New items are assigned to the array using square brackets to indicate the position in the list. The first position is position zero (not one). If an initial value is specified, it is assigned to the first position. Assigning one value is not particularly useful but is included for compatibility with other shells. Alternatively, the initial values can be assigned to specific positions by including a position in square brackets.

					$ declare -a DEPT[0]="accounting" DEPT [1]="shipping" \
					DEPT [2]="customer service"


Because of the square brackets, use curly braces to delineate the variable name and supercede the shell's pathname matching process.

$ echo "${ DEPT [0]}"
$ echo "${ DEPT [2]}"
customer service


All unassigned positions in an array have no value. The position number 5 in the PRODUCTS array, for example, is initially an empty string. It can be assigned a value of hammers with an assignment statement.

$ printf "%s" "${PRODUCTS[5]}"

$ PRODUCTS[5]="hammers"
$ printf "%s" "${PRODUCTS[5]}"


If there is an item in position zero, it is also the value returned when no position is specified.

$ PRODUCTS[0]="screwdrivers"
$ printf "%s" "$PRODUCTS"
$ printf "%s" "${PRODUCTS[0]}"


The entire array can be accessed using an asterisk (*) or an at sign (@) for the array position. These two symbols differ only when double quotes are used: The asterisk returns one string, with each item separated with the first character of the IFS variable (usually space), and the at sign returns each item as a separate string with no separation character.

$ printf "%s" "${PRODUCTS[*]}"
screwdrivers hammers
/home/kburtch [bash]
$ printf "%s" "${PRODUCTS[@]}"


In this example, the at sign version requires two separate %s formatting codes to display the array properly, one for each array item.

$ printf "%s %s\n" "${PRODUCTS[@]}"
screwdrivers hammers


Multiple values can be assigned with a list in parentheses.

$ DIVISIONS=("North America" "Europe" "Far East")
$ printf "%s\n" "${DIVISIONS[*]}"
North America Europe Far East


The list items can have an optional subscript.

$ DIVISIONS=([3]="North America" [2]="Europe" [1]="Far East")
$ printf "%s\n" "${DIVISIONS[*]}"
Far East Europe North America


Combining a list with a declare command, arrays can be assigned values at the time they are created.

The number of items in the array is returned when # is used in front of the variable name with a position of * or @. The items need not be assigned consecutively and the number doesn't reflect where the items are stored.

$ printf "%d" "${#PRODUCTS[*]}"


Individual array values can be removed with the unset command. Erasing a value by assigning the array position an empty string doesn't destroy it: The empty string is still treated as an array item whenever the items are counted.

The read command can read a list into an array using an -a (array) switch. When this switch is used, each item on the line of input is read into a separate array position.

The array attribute is the only variable attribute that cannot be turned off after it is turned on. If Bash allowed the attribute to be turned off, the data in the array would be lost when the array became a normal variable.

Exporting Variables and the Linux Environment

Shell variables exist in the script or interactive sessions only where they were declared. In order to make shell variables available outside of their place of origin, they have to be declared as exportable. Variables are marked as exportable with the export attribute using the declare -x (export) switch. The export attribute reminds the shell that you want to “export,” or provide the variable, to all programs run by the script.

For example, the program CVS requires a variable called CVSROOT to exist for all its programs.

$ declare -x CVSROOT="/home/cvs/cvsroot"


In the same way, any variables declared in your profile scripts must be exported or they won't exist at the command prompt. They will disappear after the profile scripts are finished running.

When a variable is exported, any changes made by programs executed by the script are discarded when the program completes. If a second script were to change CVSROOT to the value /home/local/cvsroot, when the second script is finished, CVSROOT will once again be /home/cvs/cvsroot. The changes are “rolled back.”

Create global constants by using both the export and read-only switches.

$ declare -rx COMPANY_BRANCH="West Coast Branch"


COMPANY_BRANCH is only a read-only variable in the current script. When it's exported to a second script, it's exported as a normal variable—the read-only effect is lost. The reason for this strange behavior is rooted in the way Linux shares environment variables between programs and has nothing to do with the Bash shell itself.

Environment variables are the variables Linux shares between a program and the program that executed it. Like layers of an onion, each program must explicitly export a variable into the environment for the next program to see it.

Although Linux has provisions for exporting environment variables, there is no way to assign any attributes to them. Linux has no notion of attributes. Bash attributes were thought up after environment variables were first invented. When Bash variables are given to Linux to share with a new program, the attributes are lost. When the second shell script starts, it has no way of knowing what the original attributes were.

The variables shared with a new program are copies of the original. If a script declares an exported variable and runs a second script, any changes made to the variable by the second script are invisible to the first. There is no way for a second script to assign a new value to a variable that the first script will see. Unlike other programming languages, exporting shell variables is a one-way street.

Suppose there are two scripts called and declares a variable and then runs the script, as shown in Listings 5.1 and 5.2.

Listing 5.1.


# This script runs first.

declare -rx COMPANY_BRANCH="West Coast Branch"
printf "%s\n" "$COMPANY_BRANCH"

exit 0



Listing 5.2.


# This script is run by

printf "This is the inner script.\n"

COMPANY_BRANCH="East Coast Branch"
printf "%s\n" "$COMPANY_BRANCH"

printf "Inner script finished\n"

exit 0



When is run, the COMPANY_BRANCH variable is read-only. However, inside, the read-only attribute has been lost. changes the variable to a new value, but when is finished, shows that the variable's value is unchanged.

$ bash
This is the inner script.
declare -x COMPANY_BRANCH="West Coast Branch"
East Coast Branch
Inner script finished
West Coast Branch


The only way to return a value to the calling program is to write it to a file (or standard output) and have the calling program read (or assign) the value back into a variable.

The eval Command

Bash performs variable substitutions as variables are encountered in a command. Before a command is executed, Bash searches the command for all dollar signs and inserts the value of variables before the command is carried out. Bash performs this substitution once. If a variable contains a value with a dollar sign in it and the value is substituted into a command, the value with the dollar sign remains unchanged.

$ declare —rx COMPANY="Value Book Resellers"
$ declare —rx TITLE='$COMPANY'
$ printf "%s\n" "$TITLE"


Before the printf is performed, Bash substitutes the value "$COMPANY" for TITLE. Bash does not repeat the substitution process to replace the COMPANY variable with "Value Book Resellers". Substitutions are performed only once.

Under rare cases, you might want to force Bash to perform an additional round of substitutions. The Bash eval command can do substitutions on demand and run the results. Take the following simple example, shown in Listing 5.3, whereby one of three variables is shown on the screen.

Listing 5.3.



shopt -s -o nounset


declare -i SALES_EAST=1000
declare -i SALES_WEST=2000
declare -i SALES_NORTH=3000

printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" \
'eval printf "%s\n" "$DISPLAY_VARIABLE"



This script can display the sales figures for one of three company branches. The constant DISPLAY_VARIABLE contains the variable to display, SALES_EAST, SALES_WEST, or SALES_NORTH. But if DISPLAY_VARIABLE is substituted, only the string "$SALES_EAST" is printed.

The backquotes run eval and perform a new set of substitutions. The results can be substituted into the original printf command. Now the results are as you expected.

$ bash
reprocessed with eval, DISPLAY_VARIABLE = 1000


In this example, Bash first processes the printf command as

printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" \
'eval printf "%s\n" $SALES_EAST'


This only prints $ SALES_EAST because Bash is finished substituting the values of variables. When Bash executes the eval command, there is a second examination of the echo command.

printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" ' printf "%s\n" 1000'



Because Bash also attempts to run the result, the echo command, a simpler version of printf, is required. eval tries to execute the re-evaluated $DISPLAY_VARIABLE as if it were a command. That is, with eval 1000, Bash would try to execute the number 1000, which is not what you want.

printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" 1000


Although not particularly realistic in this example, the eval command is useful when the user types commands to execute, or when reading commands to execute from a file. The commands can contain variables, dollar functions, and so forth, provided you use eval to process them.

A common pitfall is not following through the substitution process. Suppose, for example, that instead of assigning DISPLAY_VARIABLE the value $SALES_EAST, SALES_EAST was assigned and a second dollar sign was added to the printf statement.

printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" \
'eval printf "%s\n" "\$$DISPLAY_VARIABLE"


You would get a response similar to this:

reprocessed with eval, DISPLAY_VARIABLE = 14235SALES_EAST


In this case, the first substitution leaves the command:

  printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" \
'eval printf "%s\n" $$SALES_EAST'


But $$ is a built-in shell function. Bash doesn't understand that $SALES_EAST is supposed to be nested inside the first dollar sign: it simply reads from left to right, substituting as it does. The second substitution would execute the $$ function, not substitute the value of the SUM variable. To execute this properly, you have to escape the first dollar sign with a backslash to keep Bash from substituting it.

  printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" \
'eval printf "%s\n" "\\\$$DISPLAY_VARIABLE"'


After the first substitution, you get this:

  printf "reprocessed with eval, DISPLAY_VARIABLE = %s\n" \
'eval printf "%s\n" \$$SUM'


This prevents $$ from being treated as a built-in function: Bash substitutes for $SALES_EAST instead. You bypassed these issues in the first example when the dollar sign was inside DISPLAY_VARIABLE.

The same effect can be achieved by escaping some quotation marks in the right places.

Variables and constants form the building blocks of all scripts, but they only serve as storage containers without expressions. These are covered in the next chapter (Chapter 6, “Expressions”).



variable substitution. Let us carefully distinguish between the name of a variable and its value. If variable1 is the name of a variable, then $variable1 is a reference to its value, the data item it contains. The only time a variable appears "naked", without the $, is when declared or assigned (or when exported). Assignment may be with an = (as in var1=27), in a read statement, and at the head of a loop (for var2 in 1 2 3).

Enclosing a referenced value in double quotes (" ") does not interfere with variable substitution. This is called partial quoting, sometimes referred to as "weak quoting". Using single quotes (' ') causes the variable name to be used literally, and no substitution will take place. This is full quoting, sometimes referred to as "strong quoting".

Note that $variable is actually a simplified alternate form of ${variable}. In contexts where the $variable syntax causes an error, the longer form may work

Example 3-5. Variable assignment and substitution

   1 #!/bin/bash
   3 # Variables: assignment and substitution
   5 a=37.5
   6 hello=$a
   7 # No space permitted on either side of = sign when initializing variables.
   9 echo hello
  10 # Not a reference.
  12 echo $hello
  13 echo ${hello} #Identical to above.
  15 echo "$hello"
  16 echo "${hello}"
  18 echo '$hello'
  19 # Variable referencing disabled by single quotes,
  20 # because $ interpreted literally.
  22 # Notice the effect of different types of quoting.
  24 # --------------------------------------------------------------
  26 # It is permissible to set multiple variables on the same line,
  27 # separated by white space. Careful, this may reduce legibility.
  29 var1=variable1  var2=variable2  var3=variable3
  30 echo
  31 echo "var1=$var1   var2=$var2  var3=$var3"
  33 # --------------------------------------------------------------
  35 echo; echo
  37 numbers="one two three"
  38 other_numbers="1 2 3"
  39 # If whitespace within variables, then quotes necessary.
  40 echo "numbers = $numbers"
  41 echo "other_numbers = $other_numbers"
  42 echo
  44 echo "uninitialized variable = $uninitialized_variable"
  45 # Uninitialized variable has null value (no value at all).
  47 echo
  49 exit 0

! An uninitialized variable has a "null" value - no assigned value at all (not zero!). Using a variable before assigning a value to it will inevitably cause problems.

Parameter Substitution

Same as $parameter, i.e., value of the variable parameter.

May be used for concatenating variables with strings.

   1 your_id=${USER}-on-${HOSTNAME}
   2 echo "$your_id"
   3 #
   4 echo "Old \$PATH = $PATH"
   5 PATH=${PATH}:/opt/bin  #Add /opt/bin to $PATH for duration of script.
   6 echo "New \$PATH = $PATH"

If parameter not set, use default.
   1 echo ${username-`whoami`}
   2 # Echoes the result of `whoami`, but variable "username" is still unset.
! This is almost equivalent to ${parameter:-default}. The extra : makes a difference only when parameter has been declared, but is null.


   1 #!/bin/bash
   3 username0=
   4 echo "username0 = ${username0-`whoami`}"
   5 # username0 has been declared, but is set to null.
   6 # Will not echo.
   8 echo "username1 = ${username1-`whoami`}"
   9 # username1 has not been declared.
  10 # Will echo.
  12 username2=
  13 echo "username2 = ${username2:-`whoami`}"
  14 # username2 has been declared, but is set to null.
  15 # Will echo because of :- rather than just - in condition test.
  17 exit 0

${parameter=default}, ${parameter:=default}
If parameter not set, set it to default.

Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, as above.


   1 echo ${username=`whoami`}
   2 # Variable "username" is now set to `whoami`.

${parameter+otherwise}, ${parameter:+otherwise}
If parameter set, use 'otherwise", else use null string.

Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, as above.

${parameter?err_msg}, ${parameter:?err_msg}
If parameter set, use it, else print err_msg.

Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, as above.


   1 #!/bin/bash
   3 # Let's check some of the system's environmental variables.
   4 # If, for example, $USER, the name of the person
   5 # at the console, is not set, the machine will not
   6 # recognize you.
   8 : ${HOSTNAME?} ${USER?} ${HOME} ${MAIL?}
   9   echo
  10   echo "Name of the machine is $HOSTNAME."
  11   echo "You are $USER."
  12   echo "Your home directory is $HOME."
  13   echo "Your mail INBOX is located in $MAIL."
  14   echo
  15   echo "If you are reading this message,"
  16   echo "critical environmental variables have been set."
  17   echo
  18   echo
  20 # The ':' operator seems fairly error tolerant.
  21 # This script works even if the '$' omitted in front of
  22 # {HOSTNAME}, {USER?}, {HOME?}, and {MAIL?}. Why?
  24 # ------------------------------------------------------
  26 # The ${variablename?} construction can also check
  27 # for variables set within the script.
  29 ThisVariable=Value-of-ThisVariable
  30 # Note, by the way, that string variables may be set
  31 # to characters disallowed in their names.
  32 : ${ThisVariable?}
  33 echo "Value of ThisVariable is $ThisVariable".
  34 echo
  35 echo
  37 # If ZZXy23AB has not been set...
  38 : ${ZZXy23AB?}
  39 # This will give you an error message and terminate.
  41 echo "You will not see this message."
  43 exit 0 
Parameter substitution and/or expansion. The following expressions are the complement to the match in expr string operations (see Example 3-52). These particular ones are used mostly in parsing file path names.
${var#pattern}, ${var##pattern}
Strip off shortest/longest part of pattern if it matches the front end of variable.
${var%pattern}, ${var%%pattern}
Strip off shortest/longest part of pattern if it matches the back end of variable.

Version 2 of bash adds additional options.


   1 #!/bin/bash
   3 #                 rfe
   4 #                 ---
   6 # Renaming file extensions.
   7 #
   8 #         rfe old_extension new_extension
   9 #
  10 # Example:
  11 # To rename all *.gif files in working directory to *.jpg,
  12 #          rfe gif jpg
  14 if [ $# -ne 2 ]
  15 then
  16   echo "Usage: `basename $0` old_file_suffix new_file_suffix"
  17   exit 1
  18 fi
  20 for filename in *.$1
  21 # Traverse list of files ending with 1st argument.
  22 do
  23   mv $filename ${filename%$1}$2
  24   # Strip off part of filename matching 1st argument,
  25   # then append 2nd argument.
  26 done
  28 exit 0

Variable var expanded, starting from offset pos.
Expansion to a max of len characters of variable var, from offset pos. See Example A-6 for an example of the creative use of this operator.
First match of patt, within var replaced with replacement.

If replacement is omitted, then the first match of patt is replaced by nothing, that is, deleted.

All matches of patt, within var  replaced with replacement.

Similar to above, if replacement is omitted, then all occurrences patt are replaced by nothing, that is, deleted.


   1 #!/bin/bash
   3 var1=abcd-1234-defg
   4 echo "var1 = $var1"
   6 t=${var1#*-*}
   7 echo "var1 (with everything, up to and including first - stripped out) = $t"
   8 t=${var1%*-*}
   9 echo "var1 (with everything from the last - on stripped out) = $t"
  11 echo
  13 path_name=/home/bozo/ideas/
  14 echo "path_name = $path_name"
  15 t=${path_name##/*/}
  16 # Same effect as   t=`basename $path_name`
  17 echo "path_name, stripped of prefixes = $t"
  18 t=${path_name%/*.*}
  19 # Same effect as   t=`dirname $path_name`
  20 echo "path_name, stripped of suffixes = $t"
  22 echo
  24 t=${path_name:11}
  25 echo "$path_name, with first 11 chars stripped off = $t"
  26 t=${path_name:11:5}
  27 echo "$path_name, with first 11 chars stripped off, length 5 = $t"
  29 echo
  31 t=${path_name/bozo/clown}
  32 echo "$path_name with \"bozo\" replaced  by \"clown\" = $t"
  33 t=${path_name/today/}
  34 echo "$path_name with \"today\" deleted = $t"
  35 t=${path_name//o/O}
  36 echo "$path_name with all o's capitalized = $t"
  37 t=${path_name//o/}
  38 echo "$path_name with all o's deleted = $t"
  40 exit 0

There are several built-in variables which are set or used by Bash:

The full pathname used to execute the current instance of Bash.
If this variable is set when Bash is invoked to execute a shell script, its value is expanded and used as the name of a startup file to read before executing the script. See section Bash Startup Files.
The version number of the current instance of Bash.
A readonly array variable (see section Arrays) whose members hold version information for this instance of Bash. The values assigned to the array members are as follows:
The major version number (the release).
The minor version number (the version).
The patch level.
The build version.
The release status (e.g., beta1).
The value of MACHTYPE.
Used by the select builtin command to determine the terminal width when printing selection lists. Automatically set upon receipt of a SIGWINCH.
An index into ${COMP_WORDS} of the word containing the current cursor position. This variable is available only in shell functions invoked by the programmable completion facilities (see section 8.6 Programmable Completion).
The current command line. This variable is available only in shell functions and external commands invoked by the programmable completion facilities (see section 8.6 Programmable Completion).
The index of the current cursor position relative to the beginning of the current command. If the current cursor position is at the end of the current command, the value of this variable is equal to ${#COMP_LINE}. This variable is available only in shell functions and external commands invoked by the programmable completion facilities (see section 8.6 Programmable Completion)
An array variable consisting of the individual words in the current command line. This variable is available only in shell functions invoked by the programmable completion facilities (see section 8.6 Programmable Completion).
An array variable from which Bash reads the possible completions generated by a shell function invoked by the programmable completion facility (see section 8.6 Programmable Completion).
An array variable containing the current contents of the directory stack. Directories appear in the stack in the order they are displayed by the dirs builtin. Assigning to members of this array variable may be used to modify directories already in the stack, but the pushd and popd builtins must be used to add and remove directories. Assignment to this variable will not change the current directory. If DIRSTACK is unset, it loses its special properties, even if it is subsequently reset.
The numeric effective user id of the current user. This variable is readonly.
The editor used as a default by the `-e' option to the fc builtin command.
A colon-separated list of suffixes to ignore when performing filename completion. A file name whose suffix matches one of the entries in FIGNORE is excluded from the list of matched file names. A sample value is `.o:~'
The name of any currently-executing shell function. This variable exists only when a shell function is executing. Assignments to FUNCNAME have no effect and return an error status. If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset.
A colon-separated list of patterns defining the set of filenames to be ignored by filename expansion. If a filename matched by a filename expansion pattern also matches one of the patterns in GLOBIGNORE, it is removed from the list of matches.
An array variable containing the list of groups of which the current user is a member. Assignments to GROUPS have no effect and return an error status. If GROUPS is unset, it loses its special properties, even if it is subsequently reset.
Up to three characters which control history expansion, quick substitution, and tokenization (see section 9.3 History Expansion). The first character is the history expansion character, that is, the character which signifies the start of a history expansion, normally `!'. The second character is the character which signifies `quick substitution' when seen as the first character on a line, normally `^'. The optional third character is the character which indicates that the remainder of the line is a comment when found as the first character of a word, usually `#'. The history comment character causes history substitution to be skipped for the remaining words on the line. It does not necessarily cause the shell parser to treat the rest of the line as a comment.
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.
A value of `ignorespace' means to not enter lines which begin with a space or tab into the history list. A value of `ignoredups' means to not enter lines which match the last entered line. A value of `ignoreboth' combines the two options. Unset, or set to any other value than those above, means to save all lines on the history list. The second and subsequent lines of a multi-line compound command are not tested, and are added to the history regardless of the value of HISTCONTROL.
The name of the file to which the command history is saved. The default value is `~/.bash_history'.
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 history file is also truncated to this size after writing it when an interactive shell exits. The default value is 500.
A colon-separated list of patterns used to decide which command lines should be saved on the history list. Each pattern is anchored at the beginning of the line and must match the complete line (no implicit `*' is appended). Each pattern is tested against the line after the checks specified by HISTCONTROL are applied. In addition to the normal shell pattern matching characters, `&' matches the previous history line. `&' may be escaped using a backslash; the backslash is removed before attempting a match. The second and subsequent lines of a multi-line compound command are not tested, and are added to the history regardless of the value of HISTIGNORE.

HISTIGNORE subsumes the function of HISTCONTROL. A pattern of `&' is identical to ignoredups, and a pattern of `[ ]*' is identical to ignorespace. Combining these two patterns, separating them with a colon, provides the functionality of ignoreboth.

The maximum number of commands to remember on the history list. The default value is 500.
Contains the name of a file in the same format as `/etc/hosts' that should be read when the shell needs to complete a hostname. The list of possible hostname completions may be changed while the shell is running; the next time hostname completion is attempted after the value is changed, Bash adds the contents of the new file to the existing list. If HOSTFILE is set, but has no value, Bash attempts to read `/etc/hosts' to obtain the list of possible hostname completions. When HOSTFILE is unset, the hostname list is cleared.
The name of the current host.
A string describing the machine Bash is running on.
Controls the action of the shell on receipt of an EOF character as the sole input. If set, the value denotes the number of consecutive EOF characters that can be read as the first character on an input line before the shell will exit. If the variable exists but does not have a numeric value (or has no value) then the default is 10. If the variable does not exist, then EOF signifies the end of input to the shell. This is only in effect for interactive shells.
The name of the Readline initialization file, overriding the default of `~/.inputrc'.
Used to determine the locale category for any category not specifically selected with a variable starting with LC_.
This variable overrides the value of LANG and any other LC_ variable specifying a locale category.
This variable determines the collation order used when sorting the results of filename expansion, and determines the behavior of range expressions, equivalence classes, and collating sequences within filename expansion and pattern matching (see section 3.5.8 Filename Expansion).
This variable determines the interpretation of characters and the behavior of character classes within filename expansion and pattern matching (see section 3.5.8 Filename Expansion).
This variable determines the locale used to translate double-quoted strings preceded by a `$' (see section Locale-Specific Translation).
This variable determines the locale category used for number formatting.
The line number in the script or shell function currently executing.
Used by the select builtin command to determine the column length for printing selection lists. Automatically set upon receipt of a SIGWINCH.
A string that fully describes the system type on which Bash is executing, in the standard GNU cpu-company-system format.
How often (in seconds) that the shell should check for mail in the files specified in the MAILPATH or MAIL variables. The default is 60 seconds. When it is time to check for mail, the shell does so before displaying the primary prompt. If this variable is unset, or set to a value that is not a number greater than or equal to zero, the shell disables mail checking.
The previous working directory as set by the cd builtin.
If set to the value 1, Bash displays error messages generated by the getopts builtin command.
A string describing the operating system Bash is running on.
An array variable (see section 6.7 Arrays) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command).
If this variable is in the environment when bash starts, the shell enters POSIX mode (see section 6.11 Bash POSIX Mode) before reading the startup files, as if the `--posix' invocation option had been supplied. If it is set while the shell is running, bash enables POSIX mode, as if the command
set -o posix
had been executed.
The process ID of the shell's parent process. This variable is readonly.
If set, the value is interpreted as a command to execute before the printing of each primary prompt ($PS1).
The value of this variable is used as the prompt for the select command. If this variable is not set, the select command prompts with `#? '
The value is the prompt printed before the command line is echoed when the `-x' option is set (see section 4.3 The Set Builtin). The first character of PS4 is replicated multiple times, as necessary, to indicate multiple levels of indirection. The default is `+ '.
The current working directory as set by the cd builtin.
Each time this parameter is referenced, a random integer between 0 and 32767 is generated. Assigning a value to this variable seeds the random number generator.
The default variable for the read builtin.
This variable expands to the number of seconds since the shell was started. Assignment to this variable resets the count to the value assigned, and the expanded value becomes the value assigned plus the number of seconds since the assignment.
A colon-separated list of enabled shell options. Each word in the list is a valid argument for the `-o' option to the set builtin command (see section 4.3 The Set Builtin). The options appearing in SHELLOPTS are those reported as `on' by `set -o'. If this variable is in the environment when Bash starts up, each shell option in the list will be enabled before reading any startup files. This variable is readonly.
Incremented by one each time a new instance of Bash is started. This is intended to be a count of how deeply your Bash shells are nested.
The value of this parameter is used as a format string specifying how the timing information for pipelines prefixed with the time reserved word should be displayed. The `%' character introduces an escape sequence that is expanded to a time value or other information. The escape sequences and their meanings are as follows; the braces denote optional portions.
A literal `%'.

The elapsed time in seconds.

The number of CPU seconds spent in user mode.
The number of CPU seconds spent in system mode.

The CPU percentage, computed as (%U + %S) / %R.

The optional p is a digit specifying the precision, the number of fractional digits after a decimal point. A value of 0 causes no decimal point or fraction to be output. At most three places after the decimal point may be specified; values of p greater than 3 are changed to 3. If p is not specified, the value 3 is used.

The optional l specifies a longer format, including minutes, of the form MMmSS.FFs. The value of p determines whether or not the fraction is included.

If this variable is not set, Bash acts as if it had the value

If the value is null, no timing information is displayed. A trailing newline is added when the format string is displayed.
If set to a value greater than zero, the value is interpreted as the number of seconds to wait for input after issuing the primary prompt when the shell is interactive. Bash terminates after that number of seconds if input does not arrive.
The numeric real user id of the current user. This variable is readonly.

Recommended Links

Softpanorama hot topic of the month

Softpanorama Recommended


Internal Variables

My Favorite bash Tips and Tricks Linux Journal


FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available in our efforts to advance understanding of environmental, political, human rights, economic, democracy, scientific, and social justice issues, etc. We believe this constitutes a 'fair use' of any such copyrighted material as provided for in section 107 of the US Copyright Law. In accordance with Title 17 U.S.C. Section 107, the material on this site is distributed without profit exclusivly for research and educational purposes.   If you wish to use copyrighted material from this site for purposes of your own that go beyond 'fair use', you must obtain permission from the copyright owner. 

ABUSE: IPs or network segments from which we detect a stream of probes might be blocked for no less then 90 days. Multiple types of probes increase this period.  


Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy


War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes


Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law


Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least

Copyright © 1996-2016 by Dr. Nikolai Bezroukov. was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case is down you can use the at


The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

Last modified: July 13, 2017