Changing $PATH does wipe it at least.
It's just how bash works. If there's an entry in the session cache, it uses it. Since executable paths only get cached when you run a command successfully, this only happens when it gets moved from one directory in your PATH to another after you run it once, which isn't that common.
Setting PATH or calling hash -r will clear the session cache or one could run set +h which will disable it altogether.
It also happens when you have two executables in different directories and then you delete the one with the higher priority. Happens regularly for me after I uninstall a Linux Homebrew package.
Edit: wrong shell, zsh has rehash, bash does not.
I guess I’ve been using zsh longer than I thought, because I learned about rehash first, then made the switch to hash -r later. I started using zsh 14 years ago, and bash 20+ years ago, so my brain assumed “I learned about rehash first” must have been back when I was using bash. zsh is still “that new thing” in my head.
e.g.
hash java 2>/dev/null || printf "java command not available\n" command -v java >/dev/null || echo 'no java command in path'
...and of course, if you're going to run the command anyway, and you know an invocation that does nothing and always exits with success, you can do that too. I like doing running "--version" or equivalent in CI systems, because it has the side effect of printing what actual versions were in use during the run. java -version || { echo >&2 'no java command in path'; exit 1; }
git --version || { echo >&2 'no git command in path'; exit 1; }
gcc --version || { echo >&2 'no gcc command in path'; exit 1; }If you're targetting BASH, then "hash" is a builtin so maybe slightly quicker (not that it's likely to be an issue) and it caches the location of "java" or whatever you're looking for, so possibly marginally quicker when you do want to run the command.
Whilst running "java -version" may be useful in some scripts (my scripts often put the output into a debug function so it only runs it when I set LOG_LEVEL to a suitable value, but it writes output to a file and STDERR), you run into an issue of "polluting" STDOUT which then means that you're not going to be using your script in a pipeline without some tinkering (ironically you're putting the failure message into STDERR when you probably don't care as the script is exiting and hopefully breaking the pipeline). Also, it can take some research to figure out what invocation to use for a specific command, whereas the "hash" version can just be used with little thought.
By the way, I don't believe that ">&2" is POSIX compliant, but that's trivial to fix.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V...
The redirection operator:
[n]>&word
shall duplicate one output file descriptor from another, or shall close one. If word evaluates to one or more digits, the file descriptor denoted by n, or standard output if n is not specified, shall be made to be a copy of the file descriptor denoted by word