Fix "bash: command not found" on Linux

Quick fix

Check whether the program exists anywhere, then install the package that provides it.

type foo                      # is it known to the shell at all?
sudo apt install foo          # Debian, Ubuntu, Mint
sudo dnf install foo          # Fedora
sudo pacman -S foo            # Arch
sudo zypper install foo       # openSUSE

Just installed it? Run hash -r or open a new terminal.

Typical forms of the message:

bash: htop: command not found
-bash: ifconfig: command not found
zsh: command not found: code
sudo: docker-compose: command not found

On Ubuntu and Debian with the command-not-found package, bash adds a suggestion:

Command 'htop' not found, but can be installed with:
sudo apt install htop

What the error means

When you type a command name without a slash, the shell searches each directory listed in the PATH variable, in order, for an executable file with that name. If none matches, and it is not a shell builtin, alias or function, you get "command not found". So there are only three possibilities: the program is not installed, it is installed in a directory not in PATH, or the name you typed is not the real name.

echo "$PATH"
type -a foo
command -v foo

Cause 1: the program is not installed

Minimal and desktop installs leave out many tools (curl, vim, net-tools). Often the package name differs from the command. Ask the package manager which package ships a file:

DistroFind the package for a command
Ubuntu, Debian, Mintsudo apt install apt-file && sudo apt-file update then apt-file search bin/ifconfig
Fedoradnf provides '*/bin/ifconfig'
Archsudo pacman -Fy then pacman -F ifconfig
openSUSEcnf ifconfig or zypper search --provides /usr/bin/ifconfig

Some common surprises:

CommandPackage / modern replacement
ifconfig, netstat, routenet-tools; prefer ip and ss (iproute2), installed by default
dig, nslookupdnsutils / bind9-dnsutils (Debian), bind-utils (Fedora, openSUSE), bind (Arch)
docker-composeCompose v2 is a plugin: run docker compose (with a space)
pythonMost distros only ship python3; Ubuntu/Debian offer python-is-python3
pippython3-pip (Debian, Ubuntu), python3-pip (Fedora), python-pip (Arch)

If apt says the package does not exist, see E: Unable to locate package. For how the different package managers compare, read Linux package managers explained.

Cause 2: it is installed, but not in PATH

~/.local/bin (pip, pipx, cargo, npm, manual installs)

Tools installed per user go to ~/.local/bin, ~/.cargo/bin, ~/go/bin or similar. Many distros add ~/.local/bin to PATH only if it existed when you logged in, so the first install leaves it missing until you log in again.

ls ~/.local/bin
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

pipx ensurepath does this for you. Use ~/.zshrc if your shell is zsh.

/usr/sbin on Debian (usermod, reboot, ip6tables)

On Debian, regular users' PATH does not include /usr/sbin, and plain su keeps your user PATH. That is why usermod or visudo are "not found" after su. Use su - (login shell) or sudo, which set root's full PATH.

Snap and Flatpak

Snaps live in /snap/bin, which is added at login; right after installing snapd you need to log out and in. Flatpak apps are not commands at all; run them with flatpak run org.example.App (the ID comes from flatpak list).

A program you built or extracted yourself

Either call it by path (./bin/tool, /opt/tool/bin/tool) or link it into a PATH directory: sudo ln -s /opt/tool/bin/tool /usr/local/bin/tool. The current directory is never in PATH, so a script in it must be run as ./script.sh; if that gives "Permission denied", see bash: Permission denied.

Cause 3: stale command cache or a broken PATH

Bash remembers where it found each command. After installing, moving or uninstalling a program, clear the cache:

hash -r

If every command fails, including ls, you broke PATH, usually with a line like export PATH=~/bin (missing :$PATH) in ~/.bashrc or ~/.profile. Restore it for the session, then fix the file:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
nano ~/.bashrc

Cause 4: typo, wrong case, or Windows line endings

Linux is case-sensitive: Python3 and python3 are different. In scripts, a stray carriage return from a Windows editor produces errors like:

./setup.sh: line 2: $'\r': command not found

Convert the file to Unix line endings:

sed -i 's/\r$//' setup.sh
# or
dos2unix setup.sh

Non-breaking spaces pasted from web pages or word processors cause the same kind of error with an odd-looking command name; retype the line by hand.

Cause 5: sudo uses a different PATH

sudo replaces PATH with secure_path from sudoers, which excludes your ~/.local/bin and most custom directories. That is deliberate. Use the full path (sudo "$(command -v tool)") or install the tool system-wide in /usr/local/bin.

Still not working?

Search the whole system for the file. If it exists, you know which directory to add to PATH or link from:

sudo find / -xdev -type f -name 'foo' 2>/dev/null
ls -l "$(command -v foo)"

If find locates the file but running it by full path gives "No such file or directory", the binary is for a different architecture or its dynamic loader is missing (common with downloaded 32-bit or ARM binaries). Check with file /path/to/foo. If running it by full path gives "Permission denied", the execute bit is missing. And if a command works in one terminal but not another, compare echo $PATH and echo $SHELL in both: login shells, non-login shells, cron jobs and systemd services each build PATH differently, so cron scripts in particular should use full paths or set PATH at the top.

How to prevent it

  • Install software through your package manager when possible, so binaries land in /usr/bin.
  • Always append to PATH (PATH="$HOME/bin:$PATH"), never overwrite it.
  • Save scripts with Unix line endings; set git config --global core.autocrlf input on mixed teams.

For more on how the shell finds commands, see getting comfortable in the Linux terminal and the essential Linux commands list.

Frequently asked questions

How do I find which package provides a command?

Use apt-file search bin/name on Debian/Ubuntu, dnf provides '*/bin/name' on Fedora, pacman -F name on Arch, and zypper search --provides name or cnf name on openSUSE.

How do I add a directory to PATH permanently?

Add a line such as export PATH="$HOME/.local/bin:$PATH" to ~/.bashrc (or ~/.zshrc), then open a new terminal or run source ~/.bashrc.

Why do I get command not found right after installing something?

Bash caches command locations. Run hash -r or open a new terminal. If it still fails, the program was installed somewhere not in PATH, such as ~/.local/bin or /snap/bin.

What does $'\r': command not found mean?

The script has Windows (CRLF) line endings. Convert it with sed -i 's/\r$//' script.sh or dos2unix script.sh.

Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.