2.9. Variables in bash#

Although bash is primarily designed for managing processes, files, and representing everything as text, its syntax is in actually quite expressive and posses simple programming language constructs. For example, similar to other programming languages, bash has the ability to use variables. Variables in bash have various uses, including:

  • Defining something configurable once, and then easily reusing that definition in various later commands.

  • Holding some value that is not known in advance, for example text from user input, or the output of some command.

  • Configuring the shell that you are working in, also referred to as your working environment. This includes, for example, modifying the list of directories where the shell will look for executable programs.

Variables are commonly used in shell scripts, which will be discussed later in Section 2.10, but can also be used when you interact with the shell yourself in a terminal.

Let’s start with the basic syntax of using variables. To set or change a variable, use the following syntax in your bash shell: <variable>=<contents> For example, try this:

$ MYNAME="A. User"

Note: there should be no space before and after the = sign). Again, the assigned value = immediately follows the variable name MYNAME, without a space.

The content of a variable is just plain text, and we can now insert this text in commands, just as if we typed it ourselves. To insert a variable’s content in the comment, write $ directly followed by the variable name:

$ echo "My name is $MYNAME"

Observe that the $ is only use to ā€œlook upā€ the value of a variable, but it is not part of the name itself, so we should not include the $ when assigning a value to a variable.

Variables can be updated if needed. You can express a variable’s (new) value in terms of variables too, of course:

$ MyVal="Hello"
$ echo $MyVal
$ MyVal="$MyVal World!"
$ echo $MyVal

Exercise 2.108

Try out what happens if you use a variable that was not set yet, e.g. echo Start $KJHDS Stop; Does using an unset variable result in an error, or does it have some default value?

Exercise 2.109

Sometimes variable lookups are placed in quotes, which can have subtle different results compared to looking up the variable without quotes:

$ MSG="Hello         World!"
$ echo $MSG
$ echo "$MSG"

Why does the output of echo commands here look different? Hint: recall Section 2.4.4.1.

A common use for variables is to hold a value that we want to define once, and reuse later various times, e.g. a long filename:

$ MYFILE=/usr/share/common-licenses/GPL
$ head -1 $MYFILE
$ tail -1 $MYFILE
$ wc $MYFILE

Or to capture the output of commands, as was done in Section 2.7.3,

$ TXTFILES=$(find . -name "*.txt")
$ echo "Found: $TXTFILES"
$ wc -l $TXTFILES

Tip

You can use Bash’s Tab-completion to complete variable names. Once you have typed a $ and the first letters of the variable, a single Tab will complete the name. If multiple variables start with the same letter sequence, the completion will only complete up to the part that they share. You can press Tab twice to get all variable name options that start with what you currently typed.

You can also use this mechanism to quickly see all set variables, both regular and environment variables, by trying to complete just $. For example, by starting to type (don’t press Enter yet),

$ echo $

and then pressing Tab twice, you should see all variables.

Exercise 2.110

Try this exercise in a working directory with several files with a .txt extension. What is the difference between the two echo commands here?

$ TXTFILES=$(find . -name "*.txt")
$ echo $TXTFILES
$ echo "$TXTFILES"

Exercise 2.111

Continuing the previous exercise, what is the difference between the following two commands?

$ wc -l $TXTFILES
$ echo "$TXTFILES" | wc -l

2.9.1. Environment variables#

A variable can also be marked as a special environment variable, which have several uses.

First, environment variables can reflect properties about your shell environment, such as your username and home directory, and changing them may even affect how the shell works. In fact, some environment variables are already defined when you start a new shell.

Second, unlike regular variables, environment variables are passed on to any program that you start in the shell. This means a program may access your environment variables, and adjust their behavior based on their set values. For example, a program can obtain your home directory from an environment variable, and use it as a default location to save its files. But a program can also be programmed to look for an optional environment variable that could set to configure specific settings.

Some common environment variables are:

  • HOME is the environment variable which contains your home directory;

  • PATH contains a list of directories the shell will search for programs;

  • TERM shows you what type of terminal you are working on.

Some of the environment variables contain useful information, such as USER, and PWD etc. You can get a list of environment variables (without regular variables) and their current values with the env command,

$ env

Exercise 2.112

Get a list containing only all environment variables that contain your user name, using a single command.

Hint: use a combination of env, grep, and a pipe.

You use environment variables just as you would use regular variables, for example:

$ echo "My name is $USER and my home is $HOME"

Some of these variables affect how your shell behaves. For example, when you write ~ to represent your home directory as part of a path,

$ cd ~

your bash shell will lookup the value of the HOME variable, and replace the ~ by that value. So this line is equivalent to

$ cd $HOME

Another useful environment variable to familiarize yourself with is PATH, which we will discuss later in Section 2.10.6.

2.9.2. Defining new environment variables#

You can also define your own environment variables. To mark a variable as an environment variable, write export before setting the variable, e.g.

$ export NEWENVVAR=Hi

Check the output of env if NEWENVVAR is listed.

Exercise 2.113

Let’s try to set a variable, and test what env reports.

$ MYNAME="A. User"

Does env also show regular variables?

Exercise 2.114

Test if changing the value of an exported variable is reflected in the environment:

$ export NEWENVVAR=Hi
$ NEWENVVAR=Hello

What value does env report?

Exercise 2.115

Set an environment variable, and confirm with env that it is properly set. Then close the terminal, which will terminate your shell session. Now open a terminal again, restarting a shell. Was the environment variable still set (check with env again)?

Note

Just like aliases, custom set environment variables are lost when you logout, unless you put them in your .profile file.

2.9.3. Environment variables and child processes#

As explained before, environment variables are also accessible in child processes. We can simply test this by starting a child bash process from in your existing bash session.

Close your terminal, and open a new one, to make sure you have no custom variables set yet.

Let’s set two variables, one regular and one an environment variable:

$ TEST_REGULAR=Foo
$ export TEST_ENV=Bar

Let’s confirm that both variables can be used now

$ echo $TEST_REGULAR $TEST_ENV

should show Foo Bar.

Next, start a new bash process,

$ bash

You should see a normal prompt again, but you should be able to confirm you are now working in a child bash process,

$ pstree

Let’s check which of the two variables are now set, using the same test as before:

$ echo $TEST_REGULAR $TEST_ENV

You should be able to confirm from the output that only the exported environment variable TEST_ENV was kept.

Exercise 2.116

Does setting a variable value in a child process affect the parent process? Let’s test it by setting two different values

$ TEST_REGULAR=Ping
$ export TEST_ENV=Pong

Then terminate the child process using exit, and confirm with pstree that you are back in your original shell process.

What do you think the values of these variables in the parent process are? After you made your guess, show the variable values one more time:

$ echo $TEST_REGULAR $TEST_ENV

Exercise 2.117

As in the previous exercise, start a child bash process, and this time try to set a new environment variable that was not yet set in the original parent bash process. Now exit the child process, and check if you can print the value of that variable in the parent process, and if it shows up with env.

Draw a conclusion from your findings: Can a child process add new environment variables to a parent process?