I have heard people asking what is the difference between grep and find multiple times in the last few years. It seemed obvious to me, but maybe it’s not if you are getting started with Linux.
What is the difference between the grep and find commands?
Find is a utility to search for files and directories in the Linux filesystem based on certain criteria (e.g. filename, modify date, size, file type, etc…), grep is a utility to search for patterns in the content of files or in the output of other commands.
The difference can be subtle if you don’t have a lot of experience with Linux.
In other words, find returns files and directories in the filesystem based on your search criteria (e.g. based on their name) while grep returns files whose content matches the pattern you are looking for.
Let’s have a deeper understanding of this with some examples!
Find Command: Search For Files Based on Their Name
I want to find a file called findme.txt on my Linux system but I don’t know the exact directory for the file.
This is the perfect opportunity to use the find command that, as mentioned in the previous section, allows to find files and directories on Linux based on certain criteria.
In this case the criteria is that the filename matches “findme.txt”.
The generic syntax of the find command according to its manual is the following:
find PATH [EXPRESSION]
In simple words…
find WHERE [WHAT]
What does the find command do exactly when we run it?
It goes through the directory tree recursively for each path provided and it returns files or directories that match the EXPRESSION.
The fact that the EXPRESSION is surrounded by square brackets indicates that the expression is optional.
It’s easier to understand with an example…
I have created a test directory (called example) under /var/tmp. This is the output of the find command where path is /var/tmp/example/:
[myuser@localhost example]$ find /var/tmp/example/
/var/tmp/example/
/var/tmp/example/example_file2
/var/tmp/example/example_file3
/var/tmp/example/example_dir2
/var/tmp/example/example_dir1
/var/tmp/example/example_file1
In the output of the find command I see all the files and subdirectories inside the /var/tmp/example directory.
Now let’s add an EXPRESSION to filter the output based on the name *file1 (the expression we use to select the output coming from the find command can also contain wildcards).
The expression also contains the -name flag that allows to filter the name of files and directories found by the find command:
[myuser@localhost example]$ find /var/tmp/example/ -name *file1
/var/tmp/example/example_file1
As you can see this time the find command only returns the file /var/tmp/example/example_file1.
The expression part of the command can be used to filter the output of the find command based on other criteria. Some examples are:
- Modification time
- Size
- Permissions
- Type (e.g. regular file, directory, socket, name pipe, etc…)
I have written an article that explains the find command more in detail, have a look at it.
In this section we have seen how…
The find command allows to find files and directories in the Linux filesystem based on a search criteria provided by the user.
Grep Command: Search For Patterns Inside Files
Now, let’s have a look at how the grep command works.
The grep command can find patterns inside the content of files. If you want to know which files on your filesystem match a specific string, the grep command is the answer to that.
The syntax of the grep command is:
grep [OPTIONS] PATTERN FILE
Going back to the files and subdirectories I have created under /var/tmp/example/, I have added the string FINDME inside one of the files.
Here’s how you can find which one using the grep command:
[myuser@localhost example]$ pwd
/var/tmp/example
[myuser@localhost example]$ grep FINDME *
grep: example_dir1: Is a directory
grep: example_dir2: Is a directory
example_file2:FINDME
The last line shows that the file example_file2 contains the string FINDME.
I have used the command:
grep FINDME *
Where FINDME is the PATTERN and * (a wildcard that stands for all files) is the FILE part of the command.
You can also see the following lines in the output:
grep: example_dir1: Is a directory
grep: example_dir2: Is a directory
To avoid this error and to make sure grep searches also inside each subdirectory recursively, we can use the -r flag.
The command becomes:
[myuser@localhost example]$ grep -r FINDME *
example_dir1/example_file4:FINDME
example_file2:FINDME
As you can see, because of the -r flag, grep can also find a matching file under the directory example_dir1.
Makes sense?
Let’s recap…
The grep command allows to search for files in the Linux filesystem that contain a specific pattern inside their content.
The PATTERN we have used in our example is very simple (the word FINDME). The power of the grep command is that the PATTERN can be any complex regular expression the user wants.
Filtering Find Output with The Grep Command
I know this article is about the difference between grep and find.
But, I was thinking…
…how can I use them together?
If two things are different it doesn’t mean they cannot work well together (it could be applied to so many areas of life! :D)
In our grep example we have seen how to use the -name filter as part of the EXPRESSION.
How could I use the grep command to replace it?
(here’s the example I’m referring to)
[myuser@localhost example]$ find /var/tmp/example/ -name *file1
/var/tmp/example/example_file1
I could use the pipe and the grep command instead!
[myuser@localhost example]$ find /var/tmp/example/ | grep file1
/var/tmp/example/example_file1
Interesting, I got the exact same output!
How does it work?
The pipe is used in Linux to send the output of the command on its left to the input of the command on its right.
In this case, the output of the find command is used as input for the grep command.
So the grep command receives the following output from find:
[myuser@localhost example]$ find /var/tmp/example/
/var/tmp/example/
/var/tmp/example/example_file2
/var/tmp/example/example_file3
/var/tmp/example/example_dir2
/var/tmp/example/example_dir1
/var/tmp/example/example_dir1/example_file4
/var/tmp/example/example_file1
And only returns the lines that match the PATTERN file1.
This is very handy, and it could be applied to all Linux commands. Very powerful!
Another Way to Combine Find and Grep in Linux
There’s also another combination in which find and grep can work together.
The EXPRESSION part of the find command can also contain the -exec flag that allows to apply other Linux commands to each file identified by find.
In this way find does the filtering based on file attributes and then grep adds another level of filtering based on the content of the files.
For instance, I can search for files with a specific name using find and then verify which one of these files contains a specific PATTERN using grep.
The following command uses find to search for files whose name contains example_file and then uses grep to get all the files that contain the string “I’M HERE” inside their content.
[myuser@localhost example]$ find /var/tmp/example/ -name '*example_file*' -exec grep -H "I'M HERE" {} \;
/var/tmp/example/example_file2:I'M HERE
/var/tmp/example/example_dir1/example_file4:I'M HERE
The -H flag passed to the grep command prints the file name for each match. Without the -H flag the output would be:
[myuser@localhost example]$ find /var/tmp/example/ -name '*example_file*' -exec grep "I'M HERE" {} \;
I'M HERE
I'M HERE
Also, I know that the syntax for the -exec part of the grep expression it’s not very easy to read and to remember, especially if it’s the first time you see it.
find ... -exec COMMAND {} \;
I have an article about the find command that explains this expression in more depth (see the section “Executing Linux Commands With Find“).
Conclusion
In this article you have learned the difference between the grep and find commands in Linux.
Somehow, they both work on files but find can search for files based on their attributes (filename, permissions, size, modification time, type, etc…) while grep can identify files whose content matches specific patterns.
Two very different things!
We have also seen that find and grep can work very well together in the following ways:
- Using a pipe to send the output of the find command to the input of the grep command.
- Using the -exec expression to apply grep filtering to all the files identified by a find command.
This is it for this article!
Now it’s your time!
How are you using grep and find as Linux users or in your Bash scripts?
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design. He is a professional certified by the Linux Professional Institute.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for robotics with Raspberry Pi.
Great post! I’ve been struggling to understand the difference between grep and find for a while now, and this explanation has been incredibly helpful. Thanks for breaking it down so clearly!