•7 min read

How to Add a Directory to PATH in Linux (Permanent Fix)

How to Add a Directory to PATH in Linux (Permanent Fix)

You installed a tool, ran it, and got command not found. You know the binary exists somewhere on your system. You can see it right there when you run ls /home/user/.local/bin/my-tool. But your terminal isn't having it.

This happened to me at least three times before I actually understood what was going on. The fix is adding that directory to your PATH environment variable.

Audio Briefing
0:00 / 0:00
Part of a Series

Modern Linux & Terminal Mastery Series

Part 1 of 4

How PATH Actually Works

When you type my-tool in your terminal, your shell doesn't search your entire filesystem. It checks only the directories listed inside the PATH variable, one by one, in order. The moment it finds a match, it stops searching.

Here's what a typical PATH looks like:

/home/user/.local/bin:/usr/local/bin:/usr/bin:/bin

Those colons are separators. So the shell starts by looking in /home/user/.local/bin, then /usr/local/bin, then /usr/bin, and finally /bin. If your tool lives in /home/user/.local/bin and that directory isn't in the list, the shell will never find it.

Sound familiar?

To see your current PATH, run:

echo $PATH

That outputs a colon-separated string. Not very readable, honestly.

To check where a specific command actually comes from:

which <command>

This tells you which executable your shell resolves to, and which directory it's actually finding it in.

Advertisement

Adding a Directory Permanently

Here's where people get lost. There's temporary PATH changes and permanent PATH changes. I confused them for way too long.

Temporary means running export PATH="$PATH:/home/user/.local/bin" directly in your terminal. It works right then. Then you close that terminal, open a new one, and nothing has changed.

Permanent means editing your shell configuration file so the change survives restarts.

The file to edit depends on which shell you're using.

Bash

Edit ~/.bashrc on Linux, or ~/.bash_profile if you're on macOS. Add this line:

export PATH="$PATH:/home/user/.local/bin"

Save the file, then reload it with:

source ~/.bashrc

Or just open a new terminal window. That works too.

Zsh

Edit ~/.zshrc. The line is identical:

export PATH="$PATH:/home/user/.local/bin"

Reload with:

source ~/.zshrc

Fish

Fish is different. It doesn't use the export syntax. Instead, you edit ~/.config/fish/config.fish and add:

fish_add_path /home/user/.local/bin

Here's why I actually like Fish for this: it automatically prevents duplicate entries. And it adds the path to the front of PATH by default, which means your new directory takes priority. That's handy when you want your locally-installed tool to win over a system version.

That 'export' Trick Only Works in That Session

I learned this the hard way. I'd run export PATH="/some/path:$PATH" in my terminal, get excited that it worked, close the window, and wonder why everything reset. If it's not in your config file, it won't persist. Always.

The Mistakes That Kept Tripping Me Up

After helping a few people debug their PATH issues, I've noticed the same problems come up again and again.

The Wrong Program Gets Used

Have you ever installed something and wondered why the old version still runs? Two directories probably both have a program with that name. The one listed first in your PATH wins, every time. Run which <command> and check the path. Is it the one you expected?

If not, you've got a duplicate hiding somewhere.

Permissions Block Everything

This one's obvious in hindsight, but took me an embarrassingly long time to debug. The directory needs to be readable, and the file needs execute permissions. If either one's wrong, your shell will act like the command doesn't exist.

The fix is simple:

chmod +x /path/to/file

Quoting Saves Sanity

Always quote your PATH assignments. This works:

export PATH="$PATH:/home/user/.local/bin"

This breaks silently when paths have spaces:

export PATH=$PATH:/home/user/.local/bin

No error message. Just a broken PATH. The quotes cost you two characters. Use them.

Duplicate Entries Pile Up

If you keep adding export lines to multiple config files, or if you source your config multiple times, you end up with the same directory listed two, three, even five times in your PATH. It's not dangerous, but it's messy.

To find duplicates in your current shell:

echo $PATH | tr ':' '\n' | sort | uniq -d

Fish's fish_add_path handles this automatically. Bash and Zsh users need to be more careful.

A Step-by-Step Workflow That Actually Works

Let me walk you through the process I use now when I hit this problem.

Find where the binary actually lives

If you know the exact path, great. If not, search for it with find ~ -name "my-tool" -type f 2>/dev/null. That searches your home directory for files named "my-tool".

Check if it's already in PATH

Run echo $PATH | tr ':' '\n' | grep -x "/path/you/found". The -x flag means "exact line match". If nothing appears, it's not there yet.

Add it to your shell config

Open the right file for your shell (check with echo $SHELL). Add the appropriate line. For bash/zsh: export PATH="$PATH:/path/you/found". For fish: fish_add_path /path/you/found.

Reload and verify

Run source ~/.bashrc (or your equivalent). Then run which my-tool and confirm it points to the right location.

Advertisement

When Fish Just Feels Right

I started using Fish a couple years ago, mostly because of how it handles PATH. The fish_add_path builtin does exactly what you'd expect, never adds duplicates, and gives you a clean warning if you try to add something that doesn't exist.

Was it worth switching shells just for this? Kind of. The other quality-of-life features kept me there. But if you're happy with bash or zsh, you don't need to switch. Just be more careful with your config files.

The Mental Model That Clicked For Me

Think of PATH like a series of checkpoints. When you type a command, your shell walks down the line, checking each checkpoint in order. First stop: /home/user/.local/bin. Second stop: /usr/local/bin. Third stop: /usr/bin. The first checkpoint that has the executable you want is the one that gets used.

Nothing happens in parallel. Nothing searches the whole building. Just a sequential walk down a list.

Once that clicked, everything about PATH made sense to me.

PATH Order Matters More Than You Think

When two programs share a name, the one in the earlier PATH directory wins. Want your locally-installed version to run instead of the system version? Put your directory first in PATH. Want the system version to be the default? Put it last, or don't add your local directory at all.

Quick Reference

ShellConfig FileCommand
Bash~/.bashrcexport PATH="$PATH:/new/path"
Zsh~/.zshrcexport PATH="$PATH:/new/path"
Fish~/.config/fish/config.fishfish_add_path /new/path

Wrapping Up

PATH confusion is one of those problems that feels mysterious until it clicks. Once you understand the checkpoint analogy, everything else falls into place.

Open ~/.bashrc (for Bash) or ~/.zshrc (for Zsh) in a text editor, add export PATH="$PATH:/your/directory/path" at the end of the file, save, and run source ~/.bashrc to reload your terminal session.

Running export PATH=... directly in the command line only sets the variable for the current shell process. To make it persistent across all future terminal windows, you must add the export line to your shell configuration file (~/.bashrc or ~/.zshrc).

Prepend (export PATH="/custom/bin:$PATH") if you want your custom binary to override system versions of the same tool. Append (export PATH="$PATH:/custom/bin") if you want system binaries to maintain execution priority.


You Might Also Like

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement