Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

If you run hash it shows the path of all commands run since the hash was last reset (hash -r)

[root@c04c ~]# hash
hash: hash table empty

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   1    /usr/bin/whoami

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   2    /usr/bin/whoami

According to the man pages, the purpose of hash is:

The /usr/bin/hash utility affects the way the current shell environment remembers the locations of utilities found. Depending on the arguments specified, it adds utility loca- tions to its list of remembered locations or it purges the contents of the list. When no arguments are specified, it reports on the contents of the list. The -r option causes the shell to forget all remembered locations.

 Utilities  provided  as  built-ins  to  the  shell  are  not
 reported by hash.

Other than seeing how many times I've entered a command, I can't see the utility of hash.
It was even featured in thegeekstuff.com's top 15 useful commands

In what ways is hash useful?

share|improve this question

3 Answers 3

up vote 22 down vote accepted

hash is a bash built-in command. The hash table is a feature of bash that prevents it from having to search $PATH every time you type a command by caching the results in memory. The table gets cleared on events that obviously invalidate the results (such as modifying $PATH)

The hash command is just how you interact with that system (for whichever reason you feel you need to).

Some use cases:

  • Like you saw it prints out how many times you hit which commands if you type it with no arguments. This might tell you which commands you use most often.

  • You can also use it to remember executables in non-standard locations.

Example:

[root@policyServer ~]# hash -p /lol-wut/whoami whoami
[root@policyServer ~]# whoami
Not what you're thinking
[root@policyServer ~]# which whoami
/usr/bin/whoami
[root@policyServer ~]# /usr/bin/whoami
root
[root@policyServer ~]#

Which might be useful if you just have a single executable in a directory outside of $PATH that you want to run by just type the name instead of including everything in that directory (which would be the effect if you added it to $PATH).

An alias can usually do this as well, though and since you're modifying the current shell's behavior, it isn't mapped in programs you kick off. A symlink to the lone executable is probably the preferable option here. hash is one way of doing it.

  • You can use it to un-remember file paths. This is useful if a new executable pops up in an earlier PATH directory or gets mv'd to somewhere else and you want to force bash to go out and find it again instead of the last place it remembers finding it.

Example:

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# cp /bin/ls /lol-wut
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /bin/ls
[root@policyServer ~]# hash -d ls
[root@policyServer ~]# ls
default.ldif  newDIT.ldif  notes.txt  users.ldif
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /lol-wut/ls
[root@policyServer ~]#

The cp command caused a new version of the ls executable to show up earlier in my $PATH but didn't trigger a purge of the hash table. I used hash -d to selectively purge the entry for ls from the hash table. Bash was then forced to look through $PATH again and when it did, it found it in the newer location (earlier in $PATH than it was running before).

You can selectively invoke this "find new location of executable from $PATH" behavior, though:

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# hash ls
[root@policyServer ~]# hash
hits    command
   0    /lol-wut/ls
[root@policyServer ~]#

You'd mostly just want to do this if you wanted something out of the hash table and weren't 100% that you could logout and then back in successfully, or you wanted to preserve some modifications you've made to your shell.

To get rid of stale mappings, you can also do export PATH=$PATH which effectively just purges bash's entire hash table.

There are lots of little situations like that. I don't know if I'd call it one of the "most useful" commands but it does have some use cases.

share|improve this answer
    
I wonder where the name 'hash' does came from. What about e.g. "cache", then? :). –  Michael Aug 8 '13 at 20:11
2  
@Michael Because the hash command internally uses a hash table to store the mappings. en.wikipedia.org/wiki/Hash_table –  jlliagre Aug 8 '13 at 20:39
2  
It should be noted that hash is not bash specific, the command originated in the Bourne shell in SVR2 (though the feature of hashing paths of commands comes from csh before that) and is found in all Bourne-like and POSIX shells. –  Stéphane Chazelas Aug 8 '13 at 21:34

Here's the classic usage, simplified:

# My PATH contains /home/rici/bin as well as the Usual Suspects:
# (the real one has lots more)
$ echo $PATH
/home/rici/bin:/usr/local/bin:/usr/bin:/bin

# I've installed a program called hello in /usr/local/bin
$ $ cat /usr/local/bin/hello
#!/bin/bash

echo Hello, world. I live at $0

# The program works.
$ hello
Hello, world. I live at /usr/local/bin/hello

# Now I want to create a better hello, just for me. I put it in
# my own bin directory, and according to my PATH, it should come first.
$ cp /usr/local/bin/hello ~/bin/hello

# So now I will try running it
$ hello
Hello, world. I live at /usr/local/bin/hello

# WTF? Oh, forgot to run hash.
# Tell bash to update where to look for hello
$ hash hello
$ hello
Hello, world. I live at /home/rici/bin/hello

# Ah, all is well.
share|improve this answer
    
As noted here selective update of the hash table can be invoked with a single command hash hello. –  johntex Aug 9 at 0:42
    
@johntex: ok, changed. –  rici Aug 9 at 6:10

Here a usefull use of hash :

hash php 2> /dev/null || hash -p /usr/local/foobar/php/bin/php php 2> /dev/null

It means, if php isn't in the PATH, then use

/usr/local/foobar/php/bin/
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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