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 whoamigrep, 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 pwdcdecho, 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 pwdcd, 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.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.