# Environment Variables in Bash
by Seth Kenlon

Environment variables are global settings for your Linux, Mac, or Windows computer, stored for the system shell to use when executing commands.
Many are set by default during installation or user creation.
For instance, your home directory is set as an environment variable when you log in.

On Linux:

```
$ echo $HOME
HOME=/home/seth
```

On a Mac OS:

```
$ echo $HOME
HOME=/Users/bogus
```

And on Windows with Powershell:

```
PS C:\Users\bogus> Get-Variable HOME -valueOnly
C:\Users\bogus
```

You usually don't use environment variables directly, but they're referenced by individual applications and daemons as needed.
However, environment variables can be useful when you want to override default settings, or when you need to manage new settings that your system has no reason to create on its own.

While environment variables apply to all modern systems, this article specifically addresses environment variables in the Bash shell on Linux, BSD, Mac, and Cygwin.
Users of Microsoft's open source [Powershell](https://github.com/PowerShell/PowerShell) should refer to my article about [Environment variables in Powershell](LINK TO MY POWERSHELL ENV VAR ARTICLE).


## Environment variables

Environment variables are no different, technically, than variables.
They can be set and recalled and cleared with exactly the same syntax used for variables.
If you're not used to using variables in Bash, read my [variables in Bash](link to my VARIABLES IN BASH article) article before continuing.

Environment variables convey information about your login session to your computer.
For instance, when you type a command, the only reason your computer knows how to *find* the application corresponding to that command is because the ``PATH`` environment variable tells it where to look.
The ``PATH`` variable lists valid directories for your operating system to search for commands, whether that command is [ls](https://opensource.com/article/19/7/master-ls-command) or Firefox or [Lutris](https://opensource.com/article/18/10/lutris-open-gaming-platform) or anything else.

You can view all environment variables set on your system with the ``env`` command.
The list is long, so pipe the output through ``more`` to make it easy to read:

```
$ env | more
TERM=xterm-256color
LESSOPEN=||/usr/bin/lesspipe.sh %s
USER=seth
SUDO_EDITOR=emacs
WWW_HOME=http://mirror.lagoon.nc/pub/slackware/slackware64-current/ChangeLog.txt
VISUAL=emacs
DISPLAY=:0
PS1=$
XDG_DATA_DIRS=/home/seth/.local/share/flatpak/exports/share/:/var/lib/flatpak/exports/share/:/usr/local/share/:/usr/share/
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/snap/bin:/home/seth/bin:/home/seth/.local/bin:/snap/bin
GDMSESSION=gnome
MAIL=/var/spool/mail/seth
[...]
```

Different environment variables get used by different systems.
Your ``PATH`` variable is vital to your terminal emulator, for instance, but a lot less significant to, say, Java (which can have paths, but to important Java libraries).
However, the ``USER`` variable is used by several systems as a way to identify who is requesting a service.
For example, if you're on a multi-user system and need to check your local mailbox, your mail command knows which mail spool to retrieve based on the ``MAIL`` and ``USER`` variables.

Usually, the installer program, whether it's ``dnf`` on Fedora, ``apt`` on Ubuntu, ``brew`` on Mac, or a custom installer, updates your environment variables for a new application.
Sometimes, when you're installing something outside of your distribution's intended tool-set, you may have to manage an environment variable yourself.
Or you might choose to add an environment variable to suit your preferences.

## How to set an environment variable

If you decide you want to keep some applications in a ``bin`` folder located in your home directory, then you must add that directory to your PATH so your operating system knows to look there for applications to run when you issue a command.

If you add a location to your path the way you create throw-away variables, it works, but only as long as the shell you used to modify your system path remains open.
For instance, open a Bash shell and modify your system path:

```
$ export PATH=$PATH:/home/seth/bin
```

Confirm the result:

```
$ echo $PATH
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/snap/bin:/home/seth/bin:/home/seth/.local/bin:/snap/bin:/home/seth/bin
```

Close the session:

```
$ exit
```

Open a new one and take a look at the ``PATH`` variable:

```
$ echo $PATH
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/snap/bin:/home/seth/bin:/home/seth/.local/bin:/snap/bin
```

The variable has reverted to its default state because ``PATH`` isn't getting set with each new shell.
For that, you must configure your variables to be loaded any time a shell is launched.


## Setting environment variables in .bashrc

You can set your own persistent environment variables in your shell configuration file, the most common of which is the ``~/.bashrc`` file.
If you're a system administrator managing several users, you can also set environment variables in a script placed in the ``/etc/profile.d`` directory.

The syntax for setting a variable by configuration file is the same as setting a variable in your shell:

```
export PATH=$PATH:/snap/bin:/home/seth/bin
```

Close the current shell, or else force it to load the update config:

```
$ . ~/.bashrc
```

Finally, take another look at your system path:

```
$ echo $PATH
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/snap/bin:/home/seth/bin:/home/seth/.local/bin:/snap/bin:/home/seth/bin
```

It has been set correctly to include your additional custom directory.

## Discovering new environment variables

You can create and manipulate environment variables at will, and some applications do just that.
This means that many of your environment variables aren't used by most of your applications, and if you add your own arbitrary variables then some could be used by nothing at all.
So the question is: how do you find out which environment variables are meaningful?
The answer lies in an application's documentation.

For instance, to find out what options are available to you for your general Bash environment, you can read the Bash documentation.
While the man page mentions many important variables, the GNU info page for Bash features two exhaustive lists of useful Bourne Shell and Bash environment variables, and how each is used.

For example, in the info page list:

```
'HISTCONTROL'
    A colon-separated list of values controlling how commands are saved
    on the history list.  If the list of values includes 'ignorespace',
    lines which begin with a space character are not saved in the
    history list.  A value of 'ignoredups' causes lines which match the
    previous history entry to not be saved.  A value of 'ignoreboth' is
    shorthand for 'ignorespace' and 'ignoredups'.
    [...]
```

This tells you that the ``HISTCONTROL`` environment variable controls how your Bash history is presented, and what values you can use to customize that experience.
In this example, the ``ignoredups`` value tells the output of the ``history`` command to ignore duplicate lines.
You can test this one easily.
First, issue the same command twice in a row:

```
$ echo "hello world"
hello world
$ echo "hello world"
hello world
```

View your history, or at least the most recent entries:

```
$ history | tail -5
996  man bash
997  info bash
998  echo "hello world"
999  echo "hello world"
1000 history
```

You can see that duplicate entries are indeed listed.

Set a new environment variable in your ``.bashrc`` file based on what you have read in the info page:

```
export HISTCONTROL=$HISTCONTROL:ignorespace:ignoredups
```

Save and then load your new configuration:

```
$ source ~/.bashrc
```

Issue two commands twice in a row:

```
$ echo "hello once"
hello once
$ echo "hello once"
hello once
```

View the most recent entries in your history:

```
$ history | tail -5
1000 history
1001 emacs ~/.bashrc
1002 source ~/.bashrc
1003 echo "hello once"
1004 history
```

Duplicate entries are collapsed into one entry because of your new environment variable, just as the info page specified.

Finding relevant environment variables is usually a matter of reading the documentation for the application you want to affect, because most environment variables are specific to what one application needs from the environment to run smoothly.
For general entries, your shell's documentation is the logical place to look.
If you write scripts or applications that require environment variables, be sure to define those variables in your own documentation.