Shell Environment
PATH, .bashrc, environment variables, and configuring your shell
Quick check before you start: Can you explain what happens when you type
lsat the prompt? If you know the shell searches PATH to find/usr/bin/ls, skip to Shell Startup Files. If not, read on.Practice this topic: Shell Environment skill drill
After this lesson, you will be able to:
- Explain what environment variables are and how they differ from shell variables
- Describe how the shell uses PATH to locate commands
- Modify
~/.bashrcto make aliases and variables persistent - Use
sourceto reload shell configuration without opening a new terminal
Environment Variables
The shell maintains a set of variables that store configuration values. Programs you launch can read these variables to determine how to behave.
View the important ones:
echo $HOME # /home/student
echo $USER # student
echo $SHELL # /bin/bash
echo $PATH # colon-separated list of directories
See every environment variable at once with env:
env | head -10
Shell Variables vs. Environment Variables
A shell variable exists only in your current shell session:
MY_NAME="Alice"
echo $MY_NAME # Alice
An environment variable is visible to child processes — any program you launch from the shell:
export GREETING="Hello from the shell"
echo $GREETING # Hello from the shell
Without export, a variable stays local. With export, every program you run inherits it. In C, getenv("GREETING") only sees exported variables.
Common Pitfall: Variable assignment requires no spaces around
=. WritingX=5works. WritingX = 5does not – bash interpretsXas a command with arguments=and5.
How PATH Works
PATH is a colon-separated list of directories. When you type a command, the shell searches these directories left to right until it finds a match:
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
When you type gcc, the shell checks each directory in order:
/usr/local/sbin– not there/usr/local/bin– not there/usr/sbin– not there/usr/bin– found it – runs/usr/bin/gcc
Verify where a command lives with which:
which gcc # /usr/bin/gcc
which ls # /usr/bin/ls
Why ./hello Is Required
The current directory (.) is not in PATH by default. This is a security feature. If . were in PATH, someone could place a malicious program named ls in a shared directory, and running ls there would execute the malicious version instead of /usr/bin/ls.
The ./ prefix explicitly tells the shell: “run the program in this directory, not from PATH.”
gcc -Wall -o hello hello.c
hello # Command 'hello' not found
./hello # Hello, world!
Every lab in this course requires ./programname to run your compiled executables. This is not a bug – it is Unix enforcing explicit intent.
Adding to PATH
You can prepend a directory to PATH so the shell searches it first:
export PATH="$HOME/bin:$PATH"
This adds ~/bin to the front of PATH. The shell will now check ~/bin before any system directory. The original PATH is preserved by including $PATH at the end.
Shell Startup Files: .bashrc and .profile
Anything you type at the command line disappears when you close the terminal. To make settings permanent, put them in a startup file.
Two files matter:
| File | When it runs |
|---|---|
~/.bash_profile (or ~/.profile) |
Login shells – SSH sessions, first terminal on some systems |
~/.bashrc |
Non-login shells – every new terminal window |
On Ubuntu, ~/.bashrc is the file you edit for daily customization. If you are unsure which to use, use ~/.bashrc.
Editing .bashrc
Open it in your editor:
nano ~/.bashrc
Add lines at the bottom:
# Custom aliases
alias ll='ls -la'
alias rm='rm -i'
# Compiler defaults
export CC=gcc
export CFLAGS="-Wall -Wextra -std=c17"
# Add personal bin to PATH
export PATH="$HOME/bin:$PATH"
Save and exit. The changes take effect only after you reload the file.
Reloading with source
The source command (or its shorthand .) re-reads a file in the current shell:
source ~/.bashrc
This applies your changes immediately without opening a new terminal. You will run this command every time you modify ~/.bashrc.
. ~/.bashrc # Same as source ~/.bashrc
Aliases
Aliases let you create shortcuts for commands you type frequently:
alias ll='ls -la'
alias compile='gcc -Wall -Wextra -std=c17 -o'
alias cls='clear'
Check your current aliases:
alias # List all aliases
type ll # ll is aliased to 'ls -la'
Remove an alias:
unalias ll
Aliases defined at the command line vanish when the terminal closes. To make them permanent, add them to ~/.bashrc and run source ~/.bashrc.
Viewing All Variables with env
The env command prints every environment variable in the current shell:
env
To filter for a specific variable, pipe through grep:
env | grep PATH
env | grep SHELL
Key Insight:
envshows only exported environment variables. Shell-local variables (set withoutexport) do not appear inenvoutput. Usesetto see everything, including shell-local variables.
alias ll='ls -la' to ~/.bashrc and save the file, but typing ll gives "command not found." What is the most likely fix?~/.bashrc only writes the file to disk -- it does not re-execute it. The shell reads ~/.bashrc when a new terminal opens. To apply changes in the current terminal, run source ~/.bashrc. You do not need to restart anything.
What Comes Next
You now control your shell environment: variables configure program behavior, PATH determines which commands the shell finds, and ~/.bashrc makes your settings permanent.
In the next lesson, you will learn how the shell rewrites your commands before executing them – the expansion and quoting mechanisms that explain why echo * prints filenames instead of an asterisk, and how to control that behavior.