10  Environment

TipLearning Objectives
  • Distinguish between local shell variables and environment variables and explain how export changes inheritance.
  • Use PATH and which to locate commands and add custom script directories.
  • Create and persist aliases and configuration changes in shell startup files.

10.1 Environment variables

In the arguments and variables chapter, we introduced environment variables: variables that the shell loads automatically when it starts. System or user configuration files define these variables, and they can affect how the operating system behaves. For example, programs may use environment variables to find files or directories that they need.

Use printenv to display the variables defined in your current environment:

printenv

Here are some common environment variables:

  • $HOME stores your home directory.
  • $USER stores your username.
  • $SHELL indicates which interpreter the current shell uses. This is usually /bin/bash, but /bin/zsh is also common, especially on macOS.
  • $PATH stores a list of directories where the shell looks for executable programs. We will discuss this variable in detail below.
  • $PWD stores your current working directory. This dynamic variable changes each time you change directory.

Use the echo command to access the value of an environment variable, just as you would access any other shell variable. For example:

echo "Hello $USER!"
echo "Your home directory is located in: $HOME"
echo "Currently you're located in: $PWD"

10.1.1 Local vs global variables

A shell variable is local to the shell by default. Child processes, such as a shell script that you run from the terminal, cannot access local variables unless you export them.

For example, define the following variable in your shell:

hello_message="Hello $USER!"

You can use the variable in the current shell:

echo $hello_message
Hello participant!

However, if you include the same variable in a shell script (for example, print_hello.sh):

#!/usr/bin/env bash

echo "Greeting message:"
echo $hello_message

Then execute the script from the terminal:

bash print_hello.sh
Greeting message:

The script prints an empty value because hello_message is a local variable in the active shell. The script runs in a child process, which does not inherit local variables.

Use the export command to make a variable available to child processes:

export hello_message="Hello $USER!"

Run the script again:

bash print_hello.sh
Greeting message:
Hello participant!

The exported variable also appears in the output from printenv.

ImportantExported variables last only for the current session

Exporting a variable makes it available to child processes, but it does not make the variable permanent. If you close your terminal and start a new session, the variable will no longer be available.

To load variables automatically in future sessions, add their definitions to a configuration file such as .bashrc/.zshrc, which we discuss below.

10.2 Finding software with PATH

When you type a command, the shell uses the PATH variable to find the corresponding executable program. For example, when you type ls, cat, or grep, the shell searches a set of predefined directories.

Use the which command to see which executable the shell finds for a program:

which grep
/usr/bin/grep

The PATH variable includes /usr/bin, so the shell can find grep there:

echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin

Your PATH will probably differ from this example. Each directory appears in a colon-separated list. When you type a command, the shell searches these directories in order and runs the first matching executable. If the shell finds no match, it throws and error: command not found.

10.2.1 Adding a custom directory to PATH

You can add directories to PATH when you want to run personal scripts or locally installed software as regular commands.

The my_programs directory contains three example scripts:

cd ~/Desktop/data-shell
ls my_programs
countfiles  cow  sysinfo

These files have no extension, but they are shell scripts. You can edit them with nano or display their contents with cat. Run one of the scripts with bash:

bash my_programs/countfiles
Files in /home/participant/Desktop/data-shell/:
2

This script counts the regular files (i.e. it excludes directories) in the current directory.

To run these scripts as regular commands, first give the user execute permission. Without execute permission, you must run each script through the bash program. Use the chmod command we learned about in the permissions chapter:

chmod u+x my_programs/*
ls -l my_programs
-rwxrw-r-- 1 participant participant  80 Aug 25 11:38 countfiles
-rwxrw-r-- 1 participant participant 219 Aug 25 11:37 cow
-rwxrw-r-- 1 participant participant 158 Aug 25 11:37 sysinfo

The first three permission characters after the file type are now rwx, so the user can read, write, and execute these files. When you run an executable script, the #! shebang at the start of the file tells the operating system which interpreter to use. In this example, the scripts use bash.

Add the directory containing these scripts to the front of PATH:

PATH="$HOME/Desktop/data-shell/my_programs/:$PATH"

This assignment combines the new directory with the existing value of PATH:

  • PATH= assigns a new value to the variable.
  • $HOME/Desktop/data-shell/my_programs/ is the directory to add. Using $HOME makes the path relative to your home directory.
  • : separates directories in the PATH list.
  • $PATH preserves the directories that were already in PATH. Placing the new directory first means the shell searches it before the existing directories.

Print PATH to confirm that the new directory appears at the front:

echo $PATH
/home/participant/Desktop/data-shell/my_programs:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

You can now run any of the scripts by typing its name:

sysinfo
User:     participant
Hostname: training-pc
Kernel:   Linux
Machine:  x86_64
Uptime:   up 2 hours, 17 minutes
TipCustom scripts can use different interpreters

The #! shebang from the shell scripts chapter specifies which program should execute a script. We used #!/usr/bin/env bash for the shell scripts in this chapter, but a shebang can specify another interpreter, such as:

  • #!/usr/bin/env python3 uses Python to execute the script.
  • #!/usr/bin/env Rscript uses R to execute the script.

Any interpreter that can execute scripts can appear in a shebang.

10.3 Aliases

Adding a directory to PATH makes its scripts available as regular commands. An alias provides another way to simplify commands by assigning a short name to a command and its options.

For example, you might often use these ls options:

  • -l lists files in long format.
  • -h displays file sizes in a human-readable format.
  • -S sorts files by size.
  • --color=always always uses colours in the output.

Typing ls -l -h -S --color=always each time is repetitive. Let’s create an alias named lss (for “ls sorted by size) for this command:

alias lss="ls -l -h -S --color=always"

You can now type lss to list the contents of molecules with these options:

lss molecules
-rwxr--r-- 1 participant participant 1.8K Jun  6  2025 octane.pdb
-rwxr--r-- 1 participant participant 1.2K Jun  6  2025 pentane.pdb
-rwxr--r-- 1 participant participant 1.2K Jun  6  2025 cubane.pdb
-rwxr--r-- 1 participant participant  825 Jun  6  2025 propane.pdb
-rwxr--r-- 1 participant participant  622 Jun  6  2025 ethane.pdb
-rwxr--r-- 1 participant participant  422 Jun  6  2025 methane.pdb

10.4 Configuration files

The variable, PATH, and alias changes in the previous sections affect only the active shell. When you close the terminal and start a new session, the shell returns to its default environment.

Configuration files let you load changes whenever you start a new shell. The shell itself is a program, and different shells have different configuration files and behaviours. You can check which shell you’re using with:

echo $SHELL

For most Linux users their default shell is bash, but for macOS users it is zsh. Depending on which of these two you have, the most common configuration files are:

  • .bashrc for a bash shell
  • .zshrc for a zsh shell
ImportantSelect your shell

For your convenience, select your shell so the text below shows you the right configuration file:

All this does is use either .bashrc or .zshrc in the text that follows. But the explanations are identical otherwise.

You can inspect the contents of your configuration file with:

cat ~/__QUARTO_SHELL_FILE__

The contents of __QUARTO_SHELL_FILE__ vary between operating systems and users. Some programs also modify this file during installation, for example by adding their executable directories to PATH.

The shell treats __QUARTO_SHELL_FILE__ as a script, so you can place valid Bash commands in it. Before editing the file, create a backup so that you can restore the original if necessary:

cp ~/__QUARTO_SHELL_FILE__ ~/__QUARTO_SHELL_FILE___unix_course_bkp
Warning

Back up __QUARTO_SHELL_FILE__ before you edit it. This configuration file may contain settings that your environment needs, and an incorrect change can prevent commands or other configuration from working.

You can safely experiment if you keep the backup and restore it when necessary.

Open the file with a text editor. This example uses nano, but you can use any text editor:

nano ~/__QUARTO_SHELL_FILE__

Add your own changes at the bottom of the file and leave the existing configuration unchanged. A comment can identify the lines that you added. For example, add a welcome message that prints each time you start a session:

# User edit: add a welcome message
echo "Hello $USER - welcome back!"

Save __QUARTO_SHELL_FILE__, then start a new terminal. The new shell reads __QUARTO_SHELL_FILE__ and executes its commands, so it prints the welcome message.

You can use the same file to define persistent environment variables, update PATH, and create aliases. The exercises below let you practise these changes.

NoteHidden files

ls hides files and directories whose names start with . by default. Use ls -a to list all files, including hidden files.

Configuration files and directories often start with . to keep them out of the usual filesystem listing.

10.5 Exercises

Before starting these exercises, check which shell you’re using with:

echo $SHELL

And make your selection accordingly:

Warning

Before you edit __QUARTO_SHELL_FILE__, create a backup so that you can undo an accidental change that disrupts your environment.

ExerciseExercise 1

Level:

Earlier, we used the alias command to create an alias for ls with several options:

alias lss='ls -l -h -S --color=always'
  • Add this alias to your ~/__QUARTO_SHELL_FILE__.
  • Confirm that it persists across sessions by starting a new terminal and running lss ~/Desktop/data-shell.

Open __QUARTO_SHELL_FILE__ with a text editor such as nano:

nano ~/__QUARTO_SHELL_FILE__

Paste the alias command at the bottom of the file. Save and close the file with Ctrl + XYEnter.

Start a new terminal and run the alias:

lss ~/Desktop/data-shell
drwxr--r-- 2 participant participant  12K Feb  5  2026 hospital_records
drwxr--r-- 4 participant participant 4.0K Jun  6  2025 coronavirus
drwxr--r-- 2 participant participant 4.0K Jun  6  2025 molecules
drwxrwxr-x 2 participant participant 4.0K Aug 25 12:05 my_programs
drwxr--r-- 4 participant participant 4.0K Jun  6  2025 sequencing
-rwxr--r-- 1 participant participant  563 Jun  6  2025 README.txt
-rwxr--r-- 1 participant participant  301 Jun  6  2025 things.txt
ExerciseExercise 2

Level:

As you gain experience with the command line, you may want to create scripts or utilities of your own. Earlier, we used scripts from the my_programs directory and added that directory to PATH, which made the scripts available as regular commands.

A common practice is to create a directory in your home directory for personal utilities and add it to PATH.

  • Create a directory in your home directory for personal scripts. Choose an informative name such as utilities or personal-scripts.
  • Add a test script to the directory. You can copy one of the scripts from my_programs.
  • Add the directory to PATH persistently by editing ~/__QUARTO_SHELL_FILE__.
  • Start a new terminal and confirm that you can run the script as a command.

This directory gives you a place to keep custom scripts and utilities. When you repeat a task, consider whether a small script could save you time.

  1. Create a directory called utilities in your home directory:
mkdir ~/utilities
  1. Copy an example script into it:
cp ~/Desktop/data-shell/my_programs/countfiles ~/utilities/
  1. Open __QUARTO_SHELL_FILE__ with nano ~/__QUARTO_SHELL_FILE__ and add:
export PATH="$HOME/utilities/:$PATH"
  1. Start a new terminal and test that the countfiles command is available.
ExerciseExercise 3

Level:

Modifying __QUARTO_SHELL_FILE__ can have unintended consequences if you accidentally remove or change a setting that your environment needs.

You can reduce this risk by storing your custom configuration in a separate file and asking __QUARTO_SHELL_FILE__ to load it. For example, add this line to __QUARTO_SHELL_FILE__:

source $HOME/__QUARTO_SHELL_FILE___custom

This command tells __QUARTO_SHELL_FILE__ to read ~/__QUARTO_SHELL_FILE___custom and apply the configurations in that file.

You can then make your custom changes in ~/__QUARTO_SHELL_FILE___custom instead of editing __QUARTO_SHELL_FILE__ repeatedly.

Try it for yourself:

  • Create a file for your custom configurations with nano ~/__QUARTO_SHELL_FILE___custom.
  • Add customisations such as export PATH changes and aliases.
  • Add source $HOME/__QUARTO_SHELL_FILE___custom at the end of __QUARTO_SHELL_FILE__. Move any previous custom configurations to the new file.
  • Start a new terminal and confirm that your changes have taken effect.

10.6 Summary

TipKey Points
  • Local variables stay in the current shell, while environment variables are inherited by child processes.
    • export makes a variable available to scripts and commands started from the shell.
    • printenv lists the current environment, and echo $VAR displays a variable value.
  • PATH tells the shell where to find executable programs.
    • which shows the program the shell will run.
    • Adding a directory to PATH lets you run custom scripts as commands.
    • A shebang tells the operating system which interpreter should execute a script.
  • Aliases and shell configuration files make commands easier to use repeatedly.
    • alias creates a shortcut for a longer command.
    • .bashrc or .zshrc loads custom settings when a new shell starts.
    • Persistent changes help you keep favourite commands, variables, and script paths available.