73

In case of shell-builtins (eg type itself):

$ type type
type is a shell builtin

$ which type
<Doesn't return anything since it's a shell builtin, silently exits>

In case of commands (normally) (eg python):

$ type python
python is /usr/bin/python

$ which python
/usr/bin/python

In case of which (which is a command located at /usr/bin/which)

$ type which
which is hashed (/usr/bin/which)
$ which which
/usr/bin/which

Why does type which say that which is hashed? What is the significance of which being hashed and what does it actually mean?

1 Answer 1

86

You likely have a long PATH set and, to find an executable, the shell needs to search the path. To avoid that time consuming process every time that you want to run a program, the shell may keep a list of programs that it has already found. That list is called a "hash." When the shell says that which is hashed, it means that it has already done the PATH search and found which and saved its location in the hash.

man bash explains it as follows:

Bash uses a hash table to remember the full pathnames of executable files (see hash under SHELL BUILTIN COMMANDS below). A full search of the directories in PATH is performed only if the command is not found in the hash table.

While the hash normally speeds up shell operations, there is one case where it causes problems. If you update your system and, as a result, some executable moves to a new location, the shell may get confused. The solution is to run hash -r which causes the shell to forget all the hashed locations and search the PATH from scratch.

Why are some executables missing from the hash?

An executable is not placed in the hash until after you execute at least once. Observe:

$ type python
python is /usr/bin/python
$ python --version
Python 2.7.3
$ type python
python is hashed (/usr/bin/python)

python is hashed only after it has been executed.

How to examine what is in bash's hash

The contents of the hash are available in the bash array BASH_CMDS. You can see what is in it with the command declare -p BASH_CMDS. When a new shell or subshell is opened, the hash is empty. Commands are added one by one as they are used. From a newly opened shell, observe:

$ declare -p BASH_CMDS
declare -A BASH_CMDS='()'
$ which which
/bin/which
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" )'
$ python --version
Python 2.7.3
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" [python]="/usr/bin/python" )'
5
  • +1, pretty good explanation. But why for which and not for python?
    – jobin
    Apr 11, 2014 at 19:10
  • @Jobin See updated answer.
    – John1024
    Apr 11, 2014 at 19:53
  • 3
    It looks like the hash persists only till the time we do not exit the shell. Once we restart the terminal, it doesn't say that the command is hashed.
    – Aditya
    Apr 12, 2014 at 9:24
  • 1
    @Aditya Yes. I added a section on that to the answer.
    – John1024
    Apr 12, 2014 at 17:41
  • 4
    hash -l would be easier to use than declare -p BASH_CMDS
    – phuclv
    Nov 24, 2016 at 10:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .