Bash: Command Not Found (tested)

bash: command not found (exit code 127) means bash looked through every directory in $PATH for an executable with that exact name and found none. It is not one bug — we reproduced six different real-world ways to trigger it, and they don't all have the same fix.

1. Reproduced: the plain case — a typo

$ lss
/bin/bash: line 14: lss: command not found
$ echo $?
127

Exit code 127 is the signal: bash didn't find anything to run at all. Keep that number in mind, because the next two sections show errors that look similar but are not 127, and that difference tells you what's actually wrong.

2. Not the same thing: "Permission denied"

We made a script and removed its execute bit, then ran it:

$ chmod -x noexec.sh
$ ./noexec.sh
/bin/bash: line 18: ./noexec.sh: Permission denied
$ echo $?
126

Exit code 126, different message. bash found the file — it exists, bash can see it — but can't execute it. The fix is chmod +x, not anything PATH-related. If you see 126, stop looking for a missing command; look for a missing execute bit instead.

3. Reproduced: a script that exists, is executable, and still "isn't found"

$ chmod +x myscript.sh
$ ls myscript.sh
myscript.sh
$ myscript.sh
/bin/bash: line 22: myscript.sh: command not found
$ echo $?
127

The file is right there and executable, yet bash reports exit 127. That's because bash only searches the directories listed in $PATH — and by design, the current directory is not one of them unless you put it there. The fix is either an explicit path:

$ ./myscript.sh
hi

or adding the script's directory to $PATH if you'll run it by name repeatedly.

4. Reproduced: moving a binary breaks bash's cached location (a confusing variant)

bash remembers where it last found a command, in a per-shell cache (hash), so it doesn't re-search $PATH every time. We put a script in one directory, ran it once, then moved it to a second directory that's also on $PATH:

$ export PATH="/tmp/bashguides/dirA:/tmp/bashguides/dirB:$PATH"
$ movable
fake-tool ran
$ mv dirA/movable dirB/movable
$ movable
/bin/bash: line 24: /tmp/bashguides/dirA/movable: No such file or directory
$ echo $?
127

Note the message: "No such file or directory", not "command not found" — but still exit 127, and the practical symptom is identical: your command stops running. bash is still trying the old, cached path. The fix is to clear the cache:

$ hash -r
$ movable
fake-tool ran

hash -r forces bash to re-search $PATH from scratch. This is the variant to suspect when a command "was working five minutes ago" and the only thing that changed is that a tool got reinstalled, upgraded, or moved.

5. Reproduced: it's case-sensitive

$ Python3 --version
/bin/bash: line 18: Python3: command not found
$ python3 --version
Python 3.13.1

Unlike Windows, Linux filenames (and so command names) are case-sensitive. A capitalization typo produces the exact same "command not found" as a real typo.

6. Reproduced: a function from another file, not sourced

$ cat funcs.sh
greet() { echo "hello $1"; }
$ bash -c 'greet world'
bash: line 1: greet: command not found

The function is real and correctly written — it's just not loaded into this shell. Functions and aliases only exist in the shell session (or script) that defined or sourced them. A subshell, a fresh script, or a cron job that doesn't source funcs.sh first will not see greet, and bash reports it exactly like a typo.

$ bash -c 'source /tmp/bashguides/funcs.sh; greet world'
hello world

7. Checklist

If your script dies with an unset-variable error instead, see Bash: Unbound Variable. If chmod itself refuses to run, see chmod: Operation Not Permitted.

Frequently asked questions

What exit code means command not found?

127. We confirmed it across every command-not-found case we tested: a plain typo, a case mismatch, a script run without ./ or a PATH entry, and an unsourced function. A permission problem (file exists but isn't executable) gives exit 126 instead, with the message 'Permission denied' rather than 'command not found' — that distinction tells you immediately which kind of fix to look for.

The file is right there and executable — why does bash still say command not found?

Because bash only runs bare command names by searching $PATH, and the current directory isn't on $PATH by default. We reproduced this exactly: an executable script in the working directory failed as 'myscript.sh' but ran fine as './myscript.sh'. Use an explicit path, or add the directory to $PATH.

Why did a command stop working right after I reinstalled or moved it?

bash caches the resolved path of commands you've already run, in its hash table. We reproduced this: moving a binary to a different (still-valid) PATH directory made bash report 'No such file or directory' at the stale old path, with exit 127, until we ran hash -r to clear the cache and force a fresh PATH search.

Why does my function work in my terminal but say command not found in a script?

Functions and aliases only exist in the shell that defined them. We confirmed that a function defined in one file was invisible in a fresh bash -c subshell until we explicitly sourced that file first. A script or cron job needs its own source line — it doesn't inherit functions from your interactive shell.

Is command not found the same as Permission denied?

No, and we confirmed they're distinguishable by exit code alone: command not found is exit 127 and means bash found nothing executable by that name anywhere on $PATH. Permission denied is exit 126 and means bash found the file but it lacks the execute bit — the fix there is chmod +x, not touching $PATH at all.

Written with AI assistance. Measured on 2026-10-03 with GNU bash (Debian) on a real Linux box. Every error message and exit code below is copy-pasted output, not paraphrased. PlainHeaders is our extension; bash is free.