1. Overview

The find command is a versatile tool for locating files and directories based on specific criteria. Knowing whether the find command returns a result or not can be useful for the automation of conditional procedures in Bash scripting.

In this tutorial, we’ll explore how to check if the find command returns a match in Bash.

2. Sample Task and Setup

Let’s suppose we want to check if a regular file, named file1, exists under the dir directory. In other words, we want to indicate whether a match is found or not.

To set up a test environment, we begin by entering dir with cd and using mkdir to create three subdirectories, named dir1, dir2, and dir3, under the dir directory:

$ cd dir
$ mkdir dir1 dir2 dir3

Next, we employ touch to create a file named file1 in dir1, and we leave the other directories empty:

$ touch dir1/file1

Now, we can inspect the directory structure of dir using the tree command:

$ tree .
.
├── dir1
│   └── file1
├── dir2
└── dir3

3 directories, 1 file

As expected, we see that file1 is in dir1, and no other files exist.

Let’s explore how we can check if the find command returns a match or not.

3. The Problem With Checking the Exit Status

Often, we can check the exit status of a command, such as of grep for instance, to determine whether a match was found or not.

However, with the find command, we can’t rely on the exit status. This is because find exits successfully with an exit value of 0 whether a match is found or not. A non-zero exit status can occur, for example, if there’s an error with the usage of the command.

We can test for this fact by trying to locate a non-existent file, named file2:

$ find . -type f -name 'file2'
$ echo "$?"
0

Here, we use find to search under the current directory for a regular file named file2. The -type option allows us to specify the file type as a regular file indicated by the f letter, while the -name option specifies the name of the object to search for.

In this case, the exit status is 0, as indicated by the value of the special variable $?. This means that the find command exited successfully, although it couldn’t have located the required file.

That is why we can’t rely on the exit status of the find command to determine whether a match was found or not. Instead, we’d have to rely on the output of the command.

4. Counting Matches

One way to check for the output of the find command is to count the number of lines returned, where each line represents a match.

To count the number of lines, we can use the wc command. Let’s create a basic count_matches.sh script around that and show its contents with cat:

$ cat count_matches.sh
#!/usr/bin/env bash
lines_count=$(find . -type f -name 'file1' | wc -l)
if [ "$lines_count" -eq 0 ]; then
    echo 'nothing found'
else
    echo 'something found'
fi

The count_matches.sh script begins with the usual shebang header. Then, we use the find command to look for file1 and pass the output to the wc -l command which counts the number of lines. We also employ command substitution to save the count in a variable named lines_count.

Lastly, we use an if-else statement to test whether the value of lines_count is equal to 0. To do so, we employ the test operator represented by square brackets with the -eq option indicating equality. If the line count is 0, then we print nothing found. Otherwise, we print something found.

As usual, we grant the script execute permissions via chmod:

$ chmod +x count_matches.sh

Finally, we run the script:

$ ./count_matches.sh
something found

The result shows that we found a match because file1 does indeed exist, specifically in dir1.

5. Testing for an Empty String

Alternatively, we can test whether the output of the find command is an empty string or not:

$ [ -z "$(find . -type f -name 'file1')" ] && echo 'nothing found' || echo 'something found'
something found

Here, we use the square brackets operator with the -z option to test if a string is empty. The string itself is the output of a command substitution. We also use the && and || logical operators as a short-circuit to print nothing found if the string is empty or something found if the string isn’t empty.

6. Piping to grep

Unlike the find command, grep exits with a non-zero value if a match isn’t found. Therefore, we can make use of this fact by piping the output of the find command to grep before using the && and || logical operators:

$ find . -type f -name 'file1' |
  grep 'file1' &> /dev/null && echo 'something found' || echo 'nothing found'
something found

Notably, we use grep to match the same pattern we used in find. We also redirect stdout and stderr to the null device before using the logical operators.

7. Conclusion

In this article, we explored different methods for checking if the find command returns a match or not.

In particular, we considered counting the number of lines returned by find and comparing it to zero, as well as checking whether the command’s output is an empty string using the test operator.

Finally, we also piped the result to grep to make use of the latter’s exit status.