The problem#
While trying to develop a modification to the Pelican source, I was unexpectedly having my installed version of Pelican get run instead of the local version:
$ which pelican
/usr/local/bin/pelican
$ command -v pelican
/usr/bin/pelican
For some reason, which
was pointing to the executable I
was expecting bash
to run, but the Bash builtin
command
was telling me that bash
was running the installed
version instead.
The solution#
Use the hash
builtin to clear bash
's cache of the
location of pelican
:
$ hash -d pelican
$ command -v pelican
/usr/local/bin/pelican
The details#
Programs vs. builtins#
command
is a builtin, which uses the same code path bash
uses when running a command, so it always gives the right answer,
while which
is an external program that will use its
own logic to decide which program should be executed. We can use
type
to determine if something is a program or a builtin:
$ type command
command is a shell builtin
$ type which
which is /usr/bin/which
Path hashing#
The reason for the discrepancy is that to save time, bash
will
memoize the paths for commonly used commands so it does not have
to repeatedly look up where they are. The hash
builtin
displays the table of cached command paths:
::: bash
$ hash
hits command
14 /usr/bin/git
2 /usr/bin/wajig
2 /usr/bin/man
6 /usr/bin/gvim
118 /usr/bin/make
8 /bin/ls
2 /usr/bin/find
And type
on a program in that table will give a slightly different
output:
$ type make
make is hashed (/usr/bin/make)
Caching paths is usually fine because the locations of available
commands tend to not change often. But when I added a local version of
an existing command to /usr/local/bin/
, I violated that assumption.
The fix is to use the -d
flag of hash
to remove it
from the table or hash pelican
to recompute its location and put
the new location in the table.
Comments
Have something to add? Post a comment by sending an email to comments@aweirdimagination.net. You may use Markdown for formatting.
There are no comments yet.