Environment Variables Basics - Configuration and Practical Usage

Environment Variables Basics - Configuration and Practical Usage

What you'll be able to do

  • Check what an environment variable holds with `echo $VAR` or `env`
  • Set one with `export`, and explain how it differs from a shell variable
  • Understand how `PATH` works and fix `command not found` on your own

Prerequisites (read these first)

What You'll Learn

Target Audience: You know basic commands (pwd, cd, ls) but feel uncertain about what $HOME or export actually means.

Introduction: What Are Environment Variables?

Lina: Linny-senpai, I keep seeing $HOME and $PATH in tutorials. What are those? The $ sign feels like a magic spell.
Linny-senpai: Good question. Those are called "environment variables". Think of them as named notes your shellAn interactive program that reads the commands you type and runs them. remembers.
Lina: Named notes?
Linny-senpai: Yes. Picture a sticky note on a fridge that says "milk is on the bottom shelf". You don't have to search every time.
Linny-senpai: In the same way, the shell keeps "Lina's home directoryA container that organizes files. Same idea as a "folder" on Windows or macOS. is /home/lina" under the name HOME. Write $HOME and it hands you the value.

Words used here

  • Variable: a named box that holds a value. Write the name and you get the contents.
  • Shell variable: a variable that exists only inside the current shell.
  • Environment variable: a shell variable that is also handed to commands you start from there. export is what makes it one.
  • Child process: a command started from another command.

So an environment variable is a shell variable with a "pass this along" mark on it. Section 2 proves the difference with an experiment.

Quick Summary

Prerequisites

1. Reading Environment Variables

Conclusion: Read one with echo $VAR and all with env first.

Linny-senpai: Let's start by reading, not setting. Looking first is always safer than changing.

1-1. Show one variable: echo $VAR

$ echo $HOME
/home/lina
$ echo $USER
lina

Key Points

  • $ means "replace this with the variable's value". That replacement is called expansion.
  • Without $, echo HOME just prints the plain text "HOME".
  • Variable names are uppercase by convention. It is not required, but keeping to it makes files easier to read.
Lina: The $ makes a huge difference.
Linny-senpai: This is the first place beginners stumble. Remember it as "the $ is the switch that pulls out the value".

1-2. Show all variables: env / printenv

$ env
SHELL=/bin/bash
USER=lina
HOME=/home/lina
PATH=/usr/local/bin:/usr/bin:/bin
LANG=en_US.UTF-8
PWD=/home/lina
...

env lists every environment variable you currently have. printenv does the same job.

If the output is long, use env | less to read it one screen at a time. To find one variable, filter with env | grep PATH.

1-3. Common variables to know

Variable Meaning Example
HOME Your home directory /home/lina
USER Current username lina
PATH Directories searched for commands /usr/local/bin:/usr/bin:/bin
SHELL Your login shellThe first shell started right after a user logs in. /bin/bash
LANG Language and locale en_US.UTF-8
PWD Current directory (same as pwd) /home/lina/work
Lina: There are so many. Do I have to memorize all of them?
Linny-senpai: You don't. Day to day, only HOME and PATH really matter. For the rest, "good to know it exists" is enough.

2. Setting Variables: Assignment vs export

Conclusion: A plain assignment stays in the current shell. export makes it an environment variable that children inherit.

Linny-senpai: Now you set your own. There is a classic trap here, so let's go slowly.

2-1. Plain assignment (shell variable)

$ MY_NAME=lina
$ echo $MY_NAME
lina

Put no spaces around =.

Write MY_NAME = lina and the shell reads it as "run a command called MY_NAME". That fails. It is the most common beginner accident.

2-2. Promote to "environment variable" with export

$ MY_NAME=lina
$ export MY_NAME

Or in one shot:

$ export MY_NAME=lina
Lina: What is the real difference between assignment and export? They look the same to me.
Linny-senpai: Important question. A plain assignment is visible only inside the current shell.
Linny-senpai: Scripts and commands you launch from there — the child processes — never see it. Add export and it becomes an environment variable that children can read.

2-3. See the difference yourself

$ MY_VAR=hello
$ bash -c 'echo $MY_VAR'

Nothing is printed; you get a blank line. bash -c starts a new shell as a child process, and MY_VAR never reached it.

$ export MY_VAR=hello
$ bash -c 'echo $MY_VAR'
hello

This time it printed. The export handed the value down to the child.

Rule of thumb: If a script or another command needs the value, always use export. For a personal scratchpad, plain = is fine.

2-4. Delete a variable

$ unset MY_VAR
$ echo $MY_VAR

unset removes the variable from the current shell only.

A value written in .bashrc stays until you edit that file.

3. PATH: The Most Important Variable

Conclusion: PATH is the list of directories searched for commands. Always keep :$PATH at the end when you add one.

Lina: I keep getting "command not found" errors. Is that related to environment variables too?
Linny-senpai: Very much so. Understand PATH and you can fix "command not found" yourself.

3-1. Inspect PATH

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

Key Points

  • PATH holds a list of directories, separated by :.
  • When you type a command, the shell searches those directories left to right.
  • The first command with a matching name wins.

Think of a row of school lockers. PATH is the instruction that says which row to check first.

3-2. Find where a command lives: which

$ which ls
/usr/bin/ls
$ which python3
/usr/bin/python3
Lina: So ls actually lives in /usr/bin/.
Linny-senpai: Exactly. Typing ls works because /usr/bin is in your PATH.
Linny-senpai: Remove it from PATH and you would have to type the full path, /usr/bin/ls, every time.

3-3. Add a personal directory to PATH

Suppose you want a ~/bin folder for your own scripts.

$ mkdir -p ~/bin
$ export PATH="$HOME/bin:$PATH"

Always keep :$PATH at the end.

Writing export PATH="$HOME/bin" alone wipes out the existing PATH. Almost every command then reports "command not found". It is the most frequent accident with this variable.

If it happens, opening a new terminal restores it. As long as you did not write it into a config file, nothing else is needed.

3-4. Order changes behavior

# Prefer my own version
$ export PATH="$HOME/bin:$PATH"

# Prefer the system version (mine as fallback)
$ export PATH="$PATH:$HOME/bin"

Handy tip: When a PATH change breaks something, run which command-name. It shows exactly which file is being picked up, which is the fastest route to the cause.

3-5. Lina gets stuck: overwriting PATH

Lina: I ran export PATH="$HOME/bin" and now neither ls nor cat works. Did I break my machine?
Linny-senpai: Nothing is broken. You overwrote PATH, so the shell stopped looking in /usr/bin.
Lina: So the commands themselves were not deleted?
Linny-senpai: Right. The command files are all still there. Only the instruction about where to look is gone.
Lina: It was just the search location. That's a relief.
Linny-senpai: And the fix is easy. Open a new terminal and it is back. If you never wrote it into .bashrc, that is the whole repair.

Fixing it without a new terminal

If you would rather fix the shell you are in, type this:

$ export PATH="/usr/local/bin:/usr/bin:/bin:$PATH"

The basic commands work again. Then rewrite the line properly.

4. Persistence: Surviving the Next Login

Conclusion: export lasts only for the current shell. To keep a value, write it in ~/.bashrc and apply it with source.

Lina: I set a variable with export. When I closed the terminal, it was gone.
Linny-senpai: That is the topic of persistence. export lives for the current shell only.
Linny-senpai: The next shell has forgotten it. To keep it, write it into a config file.

First, the way back

From here on you edit a config file. A mistake in one can print an error every time you open a terminal.

Copy it before you edit.

$ cp ~/.bashrc ~/.bashrc.bak

If something goes wrong, restore the copy.

$ cp ~/.bashrc.bak ~/.bashrc
$ source ~/.bashrc

If the terminal opens and closes immediately, start a shell that skips the settings files. From another terminal, type bash --norc --noprofile, then run the cp above.

4-1. Which file should I edit?

File When it loads Typical use
~/.bashrc Every interactive bash shell Personal vars and aliases
~/.profile / ~/.bash_profile Once at login Env vars on SSH login
/etc/environment System-wide, all users Shared system settings (rootThe special administrator account allowed to do anything on the system.)

When in doubt, edit ~/.bashrc. It's the most reliable choice for GUI terminals, WSL, and SSH sessions.

4-2. Example .bashrc additions

Append to the bottom:

# Personal scripts directory
export PATH="$HOME/bin:$PATH"

# Locale
export LANG=en_US.UTF-8

# Default editor
export EDITOR=vim

4-3. Reload immediately with source

$ source ~/.bashrc

Or the dot shortcut:

$ . ~/.bashrc

Many people forget source and then wonder why PATH has not changed.

After editing a config file, always run source. Logging in again has the same effect.

Lina: What does source actually do?
Linny-senpai: It tells the shell to re-read the file inside the current shell.
Linny-senpai: Run a script the normal way and it happens in a separate process. Any export inside it never comes back to the parent shell.
Linny-senpai: source runs the lines in the shell you are in, so the settings stay.

5. Common Pitfalls

Conclusion: A missing $, spaces around =, an overwritten PATH, and the wrong quotes. Those four are the classic accidents.

Linny-senpai: You have the basics now. Let me close with the mistakes beginners hit most often.

5-1. Forgetting / adding $

# Wrong: prints the literal string "HOME"
$ echo HOME

# Right: expands the value
$ echo $HOME

5-2. Spaces around =

# Wrong: parsed as a command, fails
$ MY_VAR = hello

# Right
$ MY_VAR=hello

5-3. Wiping out PATH

# Disaster: existing PATH is gone
$ export PATH="$HOME/bin"

# Correct
$ export PATH="$HOME/bin:$PATH"

If you accidentally wipe PATH, just open a new terminal. The default comes back on its own. There is no need to edit .bashrc in a panic.

5-4. Single vs double quotes

$ NAME=lina

# Double quotes: $NAME is expanded
$ echo "Hello $NAME"
Hello lina
# Single quotes: literal, no expansion
$ echo 'Hello $NAME'
Hello $NAME

Rule of thumb: Use double quotes "..." when you want variable expansion. Use single quotes '...' for literal strings.

5-5. "I exported it but my script doesn't see it"

When you run a script as ./script.sh, variables you exported in the parent shell are inherited.

A brand-new terminal is different. It reads .bashrc from scratch, so a variable that is not written there is gone.

For variables your scripts depend on, write them into .bashrc so they are always present.

6. Hands-On Practice

Conclusion: Print a variable, add ~/bin to PATH, run your own command. Three exercises take you from setting to persisting.

Linny-senpai: Knowledge sticks faster when you type it. Let's do three exercises.

Exercise 1: Put your name in a variable and print it in the form "Hello, name".

Show Hint 1 (Direction)

First put the name in a box. Then print the contents of that box as part of a sentence. Wrap the whole sentence in quotes.

Show Hint 2 (Command name)

Assignment looks like NAME=value. Printing uses echo. Since you want the value expanded, use double quotes "...".

Show Answer
$ MY_NAME=lina
$ echo "Hello, $MY_NAME!"
Hello, lina!

Replace lina with your own name. Put no spaces around the =.

Exercise 2: Create a ~/bin directory and make it part of PATH in the next terminal too.

Show Hint 1 (Direction)

Create the directory. Then append one line to the config file that adds it to PATH. Finally re-read that config file.

Show Hint 2 (Command name)

Create with mkdir -p. Append with echo and >>. Re-read with source. The file is ~/.bashrc.

Show Answer
$ mkdir -p ~/bin
$ echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc
$ echo $PATH
/home/lina/bin:/usr/local/bin:/usr/bin:/bin

Seeing /home/yourname/bin near the front means it worked.

The single quotes matter here. They stop the expansion while writing to .bashrc, so it happens when the file is read instead.

Exercise 3: Put your own command in ~/bin and call it from anywhere.

Show Hint 1 (Direction)

Three steps. Create the file, mark it as runnable, then call it by name alone.

Show Hint 2 (Command name)

Create the file with cat > filename. Press Ctrl+D when you finish typing the contents. Mark it runnable with chmod +x. After that, the file name is the command.

Show Answer
$ cat > ~/bin/hello
#!/bin/bash
echo "Hello from my own script!"

Type those two lines, then press Ctrl+D. That saves the file.

The first line, #!/bin/bash, is the standard way to say "run this file with bash". It is called a shebang.

$ chmod +x ~/bin/hello
$ hello
Hello from my own script!

If you get command not found, check that you ran source ~/.bashrc in Exercise 2.

To delete the file, run rm ~/bin/hello. A file removed with rm does not go to a trash can; it is gone at once. Check the contents with ls ~/bin before you remove anything.

Lina: It worked. Running my own command from anywhere feels great.
Linny-senpai: That is the power of PATH. "Command not found" will not scare you anymore.

7. Review

Lina: Let me sum up. The $ is the switch that pulls out a value. export hands it to child processes.
Linny-senpai: Right. And writing it in .bashrc keeps it for the next terminal.
Lina: PATH is the list of places to search. When I see command not found, I check echo $PATH and which first.
Linny-senpai: That's it. Just never drop the :$PATH at the end when you edit it.

8. Summary

Copy-paste cheat sheet

# Inspect
echo $HOME                # Single variable
env                       # All variables
env | grep PATH           # Filter
which commandname         # Where does it live?

# Set
MY_VAR=value              # Shell variable (current shell only)
export MY_VAR=value       # Environment variable (children too)
unset MY_VAR              # Delete

# Add to PATH safely
export PATH="$HOME/bin:$PATH"   # Always append $PATH

# Persist
vim ~/.bashrc             # Append export lines
source ~/.bashrc          # Apply now

Don't do this

  • export PATH="$HOME/bin" (wipes the existing PATH)
  • MY_VAR = value (spaces around =)
  • Wrapping $HOME in single quotes and wondering why it isn't expanded
  • Editing .bashrc without source-ing it and complaining "nothing changed"

Today's 3-Line Summary

  1. $VAR pulls out a variable's value. Read the current state with echo $HOME or env
  2. Only variables marked with export are handed to child processes
  3. When you add to PATH, always keep :$PATH at the end

Next Reading