1. Overview

When running scripts that use external programs, it can be useful to verify that the program exists on the system before trying to invoke it. For instance, we might want to define some actions that the script should take if it doesn’t find a given program, such as downloading and installing it.

In this tutorial, we’ll look at commands to check for the existence of a program on a Linux device. We’ll then see how to use these commands in a Bash script.

The commands in this tutorial have been tested using Bash version 5.0 and should work on most Linux distributions.

2. Built-in Options

As with most tasks in Linux, there are multiple commands that can validate if a program is available on the system.

First, let’s define the types of files that we want to check for. We want to provide the name of a program and check for the existence of binary files with that name, omitting aliases or functions that may have the same name. Also, we can set a condition in the script to take action if the program isn’t present, using the exit status of the check.

One option we have is the built-in shell command utility. This is a POSIX-compatible way to execute a command or display information about it.

Another option is type, used to display information about the commands provided to it.

Linux also provides hash to see the full pathname of each program name passed to it.

Another popular tool for this task is which. However, we don’t include it in these examples as it has a number of limitations that could make the results of the check unreliable. For example, the behavior of which differs according to the shell that its run in. Another is that it might not detect an alias that has the same name as a program. Also, which uses the $PATH variable to search for executables, affecting the way it works.

3. command

To verify a program exists with command, we can provide the -v parameter followed by the name of the program. If it finds the relevant file, command outputs the full path to that file.

Let’s have a look at an example on the command line searching for java, which is installed:

$ command -v java
/usr/bin/java

Now, let’s compare with an example of go, which isn’t installed:

$ command -v go
$

As we see in this output, when the program doesn’t exist, the command doesn’t print anything. We can pipe the command to echo to confirm the return status:

$ command -v java | echo $? 
0
$ command -v go | echo $? 
1

We see a success error code, 0, when the program exists and 1 when it doesn’t.

4. type

The type utility is similar to command. We can get the same results as command -v with type -a, although with a small difference in the output.

Let’s again use java and go as examples here. With the -a parameter, type displays all locations of the program including aliases, built-ins, and functions. So, let’s add -a and follow it with the program name:

$ type -a java
java is /usr/bin/java
$ type -a go
bash: type: go: not found

If type finds the program, it prints the program name followed by its path. Unlike command, it shows an explicit error message if the search isn’t successful.

5. hash

We can get the full pathname of a program using hash. Run without any parameters, hash outputs information on commands remembered in the current shell session.

To get hash to determine a path, we run hash followed by the program name:

$ hash java
$

For non-existent programs, hash prints an error, as shown in this example:

$ hash go
bash: hash: go: not found

We can get hash to print its remembered locations by providing the -t parameter:

$ hash -t java
/usr/bin/java

In this case, hash sees the /usr/bin/java path for java.

6. Program Check in a Bash Script

The choice of which tool to use to check for a program depends on its availability on the system. Next, let’s see how to use each of them in a script.

Whether we choose to use command, type, or hash, we can get the script to take action on the results by redirecting the standard error stream. We do this by appending >&2 to the command. Alternatively, using an ifelse statement can define what to do depending on whether an error occurs.

Let’s see an example using command:

$ cat check_program.sh 
#!/bin/bash

if command -v java >&2; then
  echo java is available
else
  echo java is not available
fi

Now, we can see the same code snippet using type:

#!/bin/bash

if type -a java >&2; then
  echo java is available
else
  echo java is not available
fi

If we choose to use hash, there’s one additional line needed to get hash to determine the path:

#!/bin/bash

hash java
if hash -t java >&2; then
  echo java is available
else
  echo java is not available
fi

Each of the tools produces the same results in this case. The ifelse block took the content of stderr and simply printed a message depending on whether an error was produced by the command or not.

7. Conclusion

In this article, we examined different ways to check if a program is installed on a Linux system.

We started by looking at three Bash built-in commands: command, type, and hash. To get familiar with them, we demonstrated their use with existing and non-existent programs and examined the differences in their outputs. Then, we saw examples of how to use each one in a Bash script.

We looked at how to redirect the command output to capture errors. Finally, we saw how to use if statements to take different courses of action depending on whether an error was produced.