2

In my ~.profile

PATH="/path/1/":"/path/2/":"$PATH"

/path/1/ and /path/2/ both have executable files of the same name myexecutable.

In a nonlogin interactive shell, I would like to temporarily exchange the search order between the two directories.

Bash manual says for hash

The -p option inhibits the path search, and filename is used as the location of name.

My way is

$ hash -p /path/2/myexecutable
hits    command
   3    /usr/bin/which
   4    /usr/bin/psql
   1    /bin/cat
  10    /usr/bin/sudo
   1    /bin/mv
   1    /usr/bin/whereis
   3    /bin/mkdir
  19    /bin/ls

the output is the same as hash, and it doesn't seem to change myexecutable to be /path/2/myexecutable:

$ which myexecutable
/path/1/myexecutable

So what does hash -p do actually?

Thanks.

3

From help hash:

hash: hash [-lr] [-p pathname] [-dt] [name ...]

-p pathname use PATHNAME as the full pathname of NAME

So:

$ hash -p   /path/2/myexecutable   myexecutable

Will do what you want.

Of course, you can play some games with executable names:

$ hash -p   /bin/echo  myexecutable

Will run echo whenever you call myexecutable.

$ myexecutable Hello World
Hello World
  • Thanks. Is it correct that where myexecutale doesn't change after hash -p /path/2/myexecutable myexecutable? I found so, but why is it ? – Tim Jun 12 '18 at 18:15
  • Where is not a bash command. How could an external command be aware of bash internal (hash) data structures ?. You may be confused. @Tim – Isaac Jun 12 '18 at 19:14
2
$ touch file
$ ls
file
$ hash
hits    command
   1    /usr/bin/touch
   1    /bin/ls
$ hash -p /hello/world/ls ls
$ ls
bash: /hello/world/ls: No such file or directory

hash -p somepath somecommand sets the hashed path for somecommand to the given path somepath in bash.

This will generally not help you in reversing the PATH search order between two directories as you would have to use hash -p on all binaries that occur in both directories. If you only have one such binary, it may be a viable option. A more portable solution would be to simply prepend the value of PATH with the second directory.

If your original PATH is

/path/1:/path/2:...

you first turn it into

/path/2:/path/1:/path/2:...

then use hash -r to reset the hashed paths, and use the binaries as usual. These will now be picked up from /path/2 rather than from /path/1.

If you save the original PATH in a temporary variable, it's easy to restore.

Summary:

oldpath=$PATH
PATH=/path/2:$PATH
hash -r

# do stuff

PATH=$oldpath
hash -r

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.