
How To View and Update the Linux PATH Environment Variable
Learn how to view and update the Linux PATH environment variable permanently or temporarily across bash and zsh, with verification, troubleshooting, and production gotchas.
Introduction
The Linux PATH environment variable is a colon-separated list of directories the shell searches when you run a command. Each time you enter a command name such as python3, grep, or myapp, the shell checks directories in PATH from left to right and runs the first executable match it finds.
In this tutorial, you will view PATH, change it temporarily and permanently across bash and zsh, verify changes, remove entries, and troubleshoot common failures. Examples are validated on Ubuntu 22.04, Debian 12, and Rocky Linux 9.
âšī¸ Info
Commands in this guide are shown with expected output so you can compare your results and confirm each change is applied as intended.
Key Takeaways
PATHis a colon-separated list of directories the shell searches left to right when resolving a command.echo $PATHandprintenv PATHboth display the current value.export PATH=$PATH:/new/dirchangesPATHfor the current session only.- Permanent changes go in
~/.bashrcfor bash,~/.zshrcfor zsh, and/etc/environmentfor system-wide values. - Order matters: directories listed earlier in
PATHtake precedence over later ones.
Prerequisites
- A Linux system running bash or zsh (Ubuntu 22.04, Debian 12, or Rocky Linux 9).
- A non-root user with sudo privileges.
- Basic familiarity with environment variables.
Understanding How the Linux PATH Variable Works
What PATH Contains and How the Shell Uses It
PATH stores absolute directory paths separated by colons. When you run a command without a full path, your shell inspects each directory in order and executes the first matching file with execute permissions.
To inspect your PATH as one directory per line, run:
tr ':' '\n' <<< "$PATH"If the same executable name exists in more than one directory, the first directory in this list wins.
How PATH Is Inherited by Processes and Subshells
Child processes inherit exported environment variables from the parent process. A shell variable exists only in the current shell until you mark it with export. PATH follows this same rule.
MYVAR="hello"
bash -c 'echo $MYVAR' # prints nothing
export MYVAR="hello"
bash -c 'echo $MYVAR' # prints: helloStep 1 â Viewing the Current PATH Variable
Using echo to Display PATH
echo $PATH is the fastest way to see what directories your shell searches:
echo $PATHUsing printenv to Display PATH
printenv PATH reads directly from the process environment rather than through shell expansion, making it the more reliable option in scripts and non-interactive contexts:
printenv PATHđĄ Tip
Because printenv only prints exported variables, it cleanly distinguishes inherited environment variables from local shell variables â making it the safer choice inside scripts.
Reading PATH in a Script Context
Scripts invoked with bash script.sh see a different PATH than your interactive shell because they do not source ~/.bashrc. To make a script's PATH reliable, define it explicitly at the top:
#!/usr/bin/env bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echo "Script PATH: $PATH"Step 2 â Adding a Directory to PATH for the Current Session
export marks a variable for inheritance by child processes and updates it immediately in the current shell. To add a directory to PATH for the current session, prepend it for higher priority or append it for lower priority:
# Prepend: /opt/myapp/bin is checked before all existing directories
export PATH="/opt/myapp/bin:$PATH"
# Append: /opt/myapp/bin is checked after all existing directories
export PATH="$PATH:/opt/myapp/bin"â ī¸ Warning
This change applies to the current shell session only. When you close the terminal or start a new session, PATH resets to its default value. To make it permanent, see Step 3.
Step 3 â Adding a Directory to PATH Permanently
Choosing the Right Configuration File
The correct startup file depends on your shell and whether the session is login or interactive non-login. Choose the file that matches how your shell is launched:
| File | Scope | When Sourced | Shells |
|---|---|---|---|
| ~/.bashrc | Per user | Every interactive non-login bash shell | bash |
| ~/.bash_profile | Per user | Login bash shells | bash |
| ~/.profile | Per user | Login shells when no ~/.bash_profile exists | bash, sh, dash |
| ~/.zshrc | Per user | Every interactive zsh shell | zsh |
| ~/.zprofile | Per user | Login zsh shells | zsh |
| /etc/environment | System-wide | Read by PAM at login; not a shell script | All |
| /etc/profile | System-wide | Login shells | bash, sh |
| /etc/profile.d/*.sh | System-wide | Sourced by /etc/profile | bash, sh |
đĄ Tip
For most interactive use on a desktop or server where you are the only user, ~/.bashrc (bash) or ~/.zshrc (zsh) is the correct file.
Editing ~/.bashrc for Bash Users
nano ~/.bashrcScroll to the bottom and append:
export PATH="$PATH:/opt/myapp/bin"Load the change without logging out:
source ~/.bashrcEditing /etc/environment for System-Wide Changes
đ¨ Danger
Do NOT use $PATH inside /etc/environment. Variable expansion is not supported in this file. Always write the complete directory list as a literal string, or you will break PATH for all users on the system.
sudo nano /etc/environment
# Set the complete literal value:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/myapp/bin"Changes in /etc/environment take effect after the next login, not after sourcing in the current shell.
Step 4 â Verifying That PATH Changes Are Working
Using which, type, and command -v
Three commands help you verify which binary the shell will actually run:
| Command | What It Does | Best For |
|---|---|---|
| which python3 | Returns first PATH match | Quick single-path check |
| type -a python3 | Lists all matches including aliases and functions | Diagnosing version conflicts |
| command -v python3 | POSIX-portable single-path check | Scripts and portability |
which python3
# /usr/bin/python3
type -a python3
# python3 is /usr/bin/python3
# python3 is /usr/local/bin/python3
command -v python3
# /usr/bin/python3Confirming Persistence with a New Shell
Running echo $PATH in the same session that applied export does not confirm persistence. Start a fresh shell to verify:
exec bash
echo $PATHStep 5 â Removing or Deduplicating Entries from PATH
To remove /opt/myapp/bin from the current session:
PATH=$(echo "$PATH" | sed -e 's|/opt/myapp/bin:||g' -e 's|:/opt/myapp/bin||g')
export PATHTo prevent duplicate entries when sourcing config files multiple times, use a guard pattern:
case ":$PATH:" in
*":/opt/myapp/bin:"*) ;;
*) export PATH="$PATH:/opt/myapp/bin" ;;
esacđĄ Tip
Wrapping colons around both $PATH and the target directory makes the pattern match a full entry, not a substring of a longer path. This prevents false positives like /opt/myapp/bin2 matching /opt/myapp/bin.
Troubleshooting Common PATH Problems
PATH Change Not Persisting After Logout
The export command updates PATH in the current shell process only. To trace which files bash sources at login:
bash -lxv 2>&1 | head -50Wrong Version of a Binary Being Resolved
A directory containing an older version appears earlier in PATH than the newer one. Diagnose with type -a, then fix by prepending the correct directory:
type -a python3
export PATH="/opt/myapp/bin:$PATH"PATH Changes Not Applying to GUI Applications
âšī¸ Info
Most desktop environments source ~/.profile and /etc/environment at login, not ~/.bashrc. A change in ~/.bashrc only affects terminal emulators that spawn interactive non-login shells. Move the export line to ~/.profile or add the directory to /etc/environment, then log out and back in.
Managing PATH in Non-Standard Environments
PATH in Shell Scripts and Cron Jobs
â ī¸ Warning
Cron runs with a minimal default PATH (typically /usr/bin:/bin). Commands available in your interactive shell may not be found. Always set PATH explicitly at the top of your crontab.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Run myapp every hour
0 * * * * /opt/myapp/bin/myapp >> /var/log/myapp.log 2>&1PATH in Docker Containers and Dockerfiles
ENV PATH="/opt/myapp/bin:${PATH}"ENV persists across all subsequent layers and into the running container, so every RUN, CMD, and ENTRYPOINT instruction sees the updated value.
Common PATH Gotchas in Production
sudo Ignores Your PATH
Running a command with sudo often fails with "command not found" even when the command works without sudo. The cause is secure_path in /etc/sudoers, which replaces PATH entirely when sudo is invoked.
đ¨ Danger
Always use visudo to edit /etc/sudoers. Editing the file directly with a text editor and introducing a syntax error will lock you out of sudo on that system.
sudo grep secure_path /etc/sudoers
# Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# To fix, edit with visudo and add your directory:
sudo visudoSSH Non-Interactive Shells Do Not Source ~/.bashrc
Running a command over SSH with ssh user@host 'mycommand' spawns a non-interactive, non-login shell that sources neither ~/.bashrc nor ~/.bash_profile. Check whether a [ -z "$PS1" ] && return guard exists near the top of your ~/.bashrc. If it does, move your export PATH line above it.
Bash Caches Binary Locations
After updating PATH, bash may still run the old binary because it caches command locations in a hash table. Clear the cache:
hash -rCommand Resolution Precedence
PATH is not the first place bash looks when you run a command. The full resolution order is:
| Priority | Type | Example |
|---|---|---|
| 1 (highest) | Aliases | alias python3='python3.11' |
| 2 | Shell functions | function myapp() { ... } |
| 3 | Shell builtins | cd, echo, type |
| 4 | Hashed locations (binary cache) | Previously run commands |
| 5 (lowest) | PATH directory scan | /usr/bin/python3 |
đĄ Tip
This is why type -a is more useful than which for diagnosing unexpected behavior. If type python3 returns 'python3 is aliased to python', the alias takes precedence over any PATH entry.
PATH in systemd Service Units
â ī¸ Warning
When running applications as systemd services, the PATH from your user environment is not inherited. systemd starts services with a minimal environment. Set PATH explicitly in the unit file.
[Service]
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/myapp/bin"
ExecStart=/opt/myapp/bin/myappsudo systemctl daemon-reload
sudo systemctl restart myappConclusion
This tutorial walked through the full lifecycle of PATH management on Linux: reading the current value, making temporary and permanent changes across bash and zsh, choosing the right startup file for your session type, verifying that the correct binary is resolved, removing and deduplicating entries, and diagnosing failures in production environments including sudo stripping PATH, SSH non-interactive shells, stale binary caches, and systemd service isolation.
âšī¸ Info
Next steps: explore how to read and set other environmental and shell variables on Linux, learn about bash aliases and functions, or dive into an introduction to the Linux terminal.