1. Overview
In this tutorial, we’ll be looking at the Linux hash command.
2. The hash Command
When we run any commands or programs in the Linux shells, it records the location of the binary of these commands in a hash table. One benefit it provides is that the shell doesn’t have to resolve the location again using the PATH variable on subsequent invocation of the same command.
The hash command is a way that we can interact with this hash table.
2.1. Listing the Entries
To list the entries in the hash table, we can run the hash command without any arguments:
$ hash
hash: hash table empty
Since we haven’t run any commands, there are no entries in the hash table. Let’s populate the table by running some Linux commands:
$ ls >/dev/null
$ ls >/dev/null
$ which ls >/dev/null
In the example above, we run the ls command twice and the which command once. Then, we send the outputs to /dev/null.
Let’s look at the hash table now:
$ hash
hits command
1 /usr/bin/which
2 /usr/bin/ls
As expected, the table shows the path of the two commands we ran. Furthermore, it also shows the number of times we ran the command.
2.2. Adding a Command to Table Without Executing
We can run the hash command to add commands into the hash table without running it. Specifically, running the hash command followed by one or more command names without any option will add the commands to the hash table:
$ hash whoami grep xargs
$ hash
hits command
0 /usr/bin/grep
0 /usr/bin/whoami
0 /usr/bin/xargs
2 /usr/bin/ls
The first command we run adds the whoami, grep, and xargs into the hash table without running them. From the output of the second command, we can see that their hits count is 0, which means there’s no invocation of the commands happening.
2.3. Resetting the Table
The hash command resets the table when we supply the -r option:
$ hash
hits command
1 /usr/bin/which
2 /usr/bin/ls
$ hash -r
hash: hash table empty
When we reset the entries, any subsequent invocation of those commands will cause the shell to search through the PATH variable for the file path of the command.
2.4. Removing a Specific Command From Table
Instead of resetting the whole table, we can remove specific commands from the table using the -d option followed by the command name. For example, let’s remove the ls entry from the table:
$ hash
hits command
1 /usr/bin/which
2 /usr/bin/ls
$ hash -d ls
$ hash
hits command
1 /usr/bin/which
From the example above, we use the -d option to remove the ls command from the table, leaving the which command in the table untouched.
2.5. Setting Path for a Command
Usually, we’ll run a command and have the shell resolve its location for us by checking the directories in the PATH environment. The hash command provides us a way to set the path of commands manually using the –p option. Generally, we specify the -p option followed by the path to the binary and then the command name we want to associate it with:
hash -p COMMAND_PATH COMMAND_NAME
Here COMMAND_PATH is the path to the binary we want to associate COMMAND_NAME with.
For example, we can link a non-existent another-date command to the /usr/bin/date binary:
$ another-date
bash: another-date: command not found
$ hash -p /usr/bin/date another-date
$ another-date
Fri Apr 7 14:04:06 GMT 2023
Initially, the shell complains that the another-date command does not exist. Then, we manually insert the entry into the hash table using the -p option. After that, running the command prints the current date and time.
We can also leverage the -p option to bypass the PATH variable lookup sequence. For example, let’s consider the following PATH variable:
$ echo $PATH
/opt/version1;/opt/version2
Additionally, both the /opt/binary/version1 and /opt/binary/version2 directories have a binary with the same name, deploy-server:
$ ls /opt/version1
deploy-server
$ ls /opt/version2
deploy-server
When we rely on the shell to resolve the deploy-server command, it will resolve to the /opt/version1/deploy-server command path because it precedes the version2 directory.
To prioritize the binary in the version2 directory without changing the PATH variable, we can use the -p option to set it manually:
$ hash -p /opt/version2/deploy-server deploy-server
This forces the shell to use deploy-server in the version2 directory whenever we invoke the deploy-server command.
3. Built-Ins Commands Aren’t Reported
The hash command doesn’t report any shell built-in commands. These include pwd, cd, echo, and hash. First, let’s reset the table:
$ hash -r
$ hash
hash: hash table empty
Then, we run some of those built-in commands, such as pwd, cd, and echo:
$ pwd
/home/bob
$ cd
$ echo "hello"
hello
Finally, we can check the hash table and see for ourselves that the hash command still reports that the table is empty:
$ hash
hash: hash table empty
4. Conclusion
In this article, we first discussed what the hash command is. Then, we saw some options we can apply to the command to add, reset, and list entries.
Finally, we also learned that the hash command doesn’t report all the built-in commands.