Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

By updated

Improve this page

The shell keeps information in environment variables: your user name, your home directory, the list of folders where it looks for commands. Knowing how to read and change them is essential to understand how the system behaves. This guide covers the most common variables and the commands to handle them.

What you will learn

  • Show the value of a variable with echo
  • List every variable with env
  • Create a variable and make it available with export
  • Know the essential variables: PATH, HOME, USER, SHELL
  • Delete a variable with unset
  • Diagnose the "command not found" problem

What is an environment variable?

An environment variable is a name=value pair kept in memory by the shell. Every program started from the terminal inherits these variables.

They configure the behaviour of the system without changing any file. For example, LANG sets the language of messages and PATH says where to look for commands.

How do you show a variable?

The echo command followed by $NAME prints the contents of a variable:

Terminal window
echo $HOME
Output
/home/bob

The $ sign tells the shell to replace the name with its value. Without the $, the shell prints the literal text:

Terminal window
echo HOME
Output
HOME

Which variables are essential?

Here are the variables you will meet most often. They are set by the system at login, and most programs read them:

VariableContentsExample
HOMEHome directory/home/bob
USERName of the logged-in userbob
SHELLConfigured login shell/bin/bash
PATHList of folders where commands are looked up/usr/local/bin:/usr/bin:/bin
PWDCurrent directory/home/bob/projects
LANGLanguage and encodingen_US.UTF-8
HOSTNAMEName of the machineserver01

To show any of them, use echo with the $ in front of the name:

Terminal window
echo $USER
echo $SHELL
echo $LANG

How do you list every variable?

The env command prints every exported environment variable:

Terminal window
env

The output is long. To look for a given variable, combine it with grep:

Terminal window
env | grep PATH
Output
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

How do you create a variable?

To create a variable, write NAME=value with no spaces around the =:

Terminal window
FIRSTNAME="Alice"
echo $FIRSTNAME
Output
Alice

This writing rule is not a style convention. FIRSTNAME = "Alice" causes an error, because the shell then reads FIRSTNAME as a command to run, with = and "Alice" as arguments. The message therefore speaks of a command not found and never mentions the assignment. Always write NAME=value, with no space on either side.

Local vs exported variable

A variable created with NAME=value only exists in the current shell. The programs started from that shell do not see it.

To make it visible to child programs, use export:

Terminal window
export FIRSTNAME="Alice"

To check, start a subshell and print the variable:

Terminal window
bash -c 'echo $FIRSTNAME'

Without export, the result is empty. With export, the value shows.

Create and export in one go

You can create and export in a single line:

Terminal window
export PROJECT="my-site"

How does PATH work?

PATH is the most important variable for running commands. It holds a list of folders separated by a colon, the : character. Remember this separator, it is neither the space nor the comma: a value written with the wrong character produces no error, it simply makes every folder in the list invisible.

Terminal window
echo $PATH
Output
/usr/local/bin:/usr/bin:/bin

When you type a command such as ls, the shell looks for a file named ls in each folder of PATH, in order:

  1. It looks in /usr/local/bin/ → not found
  2. It looks in /usr/bin/ → found! It runs /usr/bin/ls

You can check where a command lives with which, which follows the same order as the shell:

Terminal window
which ls
Output
/usr/bin/ls

Add a folder to PATH

To add a folder temporarily (for example ~/scripts), put it in front of the existing $PATH:

Terminal window
export PATH="$HOME/scripts:$PATH"

This change is temporary: it disappears when the terminal closes. To make it permanent, add the line to ~/.bashrc (see the Customise your shell guide).

How do you delete a variable?

The unset command deletes a variable, which you can check with a second echo:

Terminal window
export TEST="hello"
echo $TEST
unset TEST
echo $TEST

The last line prints nothing: the variable no longer exists.

Troubleshooting

Variable problems all look the same: nothing shows up, or a command stays not found, and no message mentions a variable. Two causes cover most cases, a folder missing from PATH and a setting written in the wrong configuration file. The table sorts them by symptom, since that is what you observe.

SymptomLikely causeFix
command: command not foundThe folder holding the command is not in $PATHecho $PATH then export PATH="/missing/path:$PATH"
echo $MY_VAR shows nothingVariable not defined or not exportedCheck with env | grep MY_VAR
Variable lost after closing the terminalVariable not added to .bashrcAdd export MY_VAR="value" to ~/.bashrc
NAME = value gives an errorSpaces around the =Write NAME=value with no spaces
A child program does not see the variableexport forgottenUse export NAME=value
Variable missing with ssh host 'command' although it works in an interactive sessionIt is declared in ~/.bash_profile, never read in that caseDeclare it in ~/.bashrc, at the top of the file on Debian/Ubuntu: that is the file a remote command reads
~/.bashrc ignored although it existsBash stops at the first of the three login files foundCheck for ~/.bash_profile then ~/.bash_login: the first one found hides the next ones

Why does a variable disappear in automation?

This point explains almost every "my variable works over interactive SSH and disappears in the script", and it contradicts the usual shortcut, ".bash_profile for login shells, .bashrc for interactive shells".

A remote command is neither one nor the other. Measured on AlmaLinux 10 with probes in both files:

Terminal window
ssh server 'echo "$-"; shopt -q login_shell && echo login || echo non-login'
hBc
non-login

$- contains no i, so the session is not interactive, and it is not a login shell either. Yet only the probe in ~/.bashrc fired: bash reads it in this precise case, on the strength of the SSH_CLIENT variable.

One caveat applies to Debian and Ubuntu: their default ~/.bashrc opens with a guard that returns as soon as $- contains no i. Bash does read the file, but only runs these few lines of it:

Terminal window
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac

On these distributions, a variable meant for remote commands is therefore declared above this block, at the top of the file. Placed further down, it is never read, again without the slightest error message.

A corollary follows for the reading order. At login, bash stops at the first file found among ~/.bash_profile, ~/.bash_login and ~/.profile, and never reads the others. Settings placed in ~/.profile while a ~/.bash_profile exists are therefore never applied, without the slightest message.

Put it into practice

Reading a guide about variables does not replace the moment when your own export survives (or not) in a subshell. This lab has you write an env.sh file that exports variables, reuses one inside another and adds a directory at the front of PATH: the whole thing is checked by loading it with source in a fresh shell.

Key points

  • An environment variable is a name=value pair inherited by child programs.
  • echo $NAME shows the value, env lists every exported variable.
  • export makes a variable visible to subprocesses.
  • PATH decides where the shell looks for commands.
  • Changes are temporary unless added to ~/.bashrc.
  • unset deletes a variable.

Knowledge check

Check that the essentials of this guide stuck. The questions cover only what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn