Observation: I have an executable named foo, located in /b/foo. It is compiled against an old header of a dynamic library, causing it to segfault when executed:
$ foo Segmentation fault. // Expected behaviour.
Now, I compile a new version of foo to /a/foo against the new dynamic library that should execute just fine. Directory a/ is in my $PATH before b/, so /a/foo should be selected:
$ which foo /a/foo
When I execute foo, the following happens:
$ foo Segmentation fault.
Therefore, it seems that /b/foo gets executed, whereas "which" tells me that /a/foo should be executed. To make things weirder, when I run the full path $(which /a/foo), things run fine:
$ /a/foo OK! $ cp /a/foo . $ ./foo OK!
To go yet one step further, if I now delete /a/foo:
$ rm /a/foo
Then /b/foo must surely be chosen, right?
$ which foo /b/foo $ foo bash: /a/foo: No such file or directory $ $(which foo) Segmentation fault. // Expected result.
Fix: Source .bash_profile and .bashrc and the problem disappears.
Reproducibility: Every time. Just remove /a/foo, source ~/.bash_profile, create /a/foo, and the above observation re-occurs.
Question: Does anyone have an idea what went wrong here?
Hypothesis: "which" is up-to-date, but the system chooses based on "what was used to be the case". In my example above, /a/foo did not yet exist when the terminal was opened: I had only just created it. Therefore, when /a/foo was created, "which" did detect /a/foo, but the system still chose /b/foo, because it was somehow out of sync? But why is the system out of sync?
Bash caches the location of commands. Use
hash foo to force it to update the cache.
which is a separate command that doesn't tell you where your shell is actually looking; it just consults the
$PATH environment variable. In bash, you should use
$ type foo foo is hashed (/a/foo)
$PATH. If it finds it, it stores the result in the cache for next time. — Jun 12, 2017 at 15:38