6 practical scenarios to use grep recursive with examples

How do I grep for a pattern inside all directories and sub-directories of my Linux server? Is it possible to perform grep recursively? Can you show me some examples to grep for a pattern or a string recursively across multiple directories?

With grep utility we have two arguments which can help you perform grep recursively, from the man page of grep

-r, --recursive
      Read  all files under each directory, recursively, following symbolic links only if they are on the command line.
      Note that if no file operand is given, grep searches the working directory.  This is equivalent to the -d recurse
      option.

-R, --dereference-recursive
      Read all files under each directory, recursively.  Follow all symbolic links, unlike -r.

In this tutorial I will share multiple methods with examples to grep recursively for different scenarios and you can choose the best one which suits your requirement.

 

1. Grep for string in a file recursively inside all sub-directories

The first scenario which we will cover is where in you have to grep for a string inside all sub-directories. For this we can just use "grep -r" without any additional arguments. The general syntax here would be:

grep [-r|--recursive] [PATH]

 

Example 1: Search for string "test" inside /tmp/dir recursively

To get all the files which contains "test" string under /tmp/dir, you can use

# grep -r test /tmp/dir/*

OR

# grep -r test /tmp/dir/

OR
Navigate inside the target path

# cd /tmp/dir

And grep for your string

# grep -r test .

All of these commands would search /tmp/dir directory and all sub-directories inside this folder for all the files which contains the word "test" or any matching string with word "test"

NOTE:

This command will search for all the strings containing "test" such as "latest", "testing" etc

 

2. Grep exact match in a file recursively inside all sub-directories

In this example we will grep for exact pattern instead of all the matching words containing our string. So assuming now we only wish to grep the files which contains "test", but we should not get the output from matching patterns such as "testing", "latest" etc. The general syntax would be:

grep [-r|--recursive] [-w|--word-regexp] [PATH]

 

Example 1: Grep for exact match recursively

To get all the files which contains exact pattern "test" string under /tmp/dir, you can use

# grep -rw test /tmp/dir/*

OR

# grep -rw test /tmp/dir/

OR
Navigate inside the target path

# cd /tmp/dir

And grep for your string

# grep -rw test .

 

3. Grep for a string only in pre-defined files

We can also define filename in plain text format or regex which should be searched to grep the provided pattern. For example, I wish to grep for "test" string but only in files which contain "lvm" or "linux" in the filename.

In the below examples we will "Search for test string in file that contains "lvm" and "linux" in the filename". Now we can have a file such as my-lvm.conf, dummy-lvm.conf, store-linux.config so all such files would be eligible when we use "lvm" and "linux" as our regex for filename:

 

Method 1: Use find with exec

In this example we will use find with exec to search for specific files and grep for our string. Syntax to use with single filename:

find PATH -type f -name <filename> -exec grep [args] [pattern] {} +

Syntax to use with multiple filenames:

find PATH -type f \( -name <filename-1> -o -name <filename-2> \) -exec grep [args] [pattern] {} +

So below example would cover our scenario.

# find /tmp/ \( -name "*linux*" -o -name "*lvm*" \)  -type f -exec grep -w test {} +

 

Find with exec to search recursively
Find with exec to search recursively

 

Method 2: using find with xargs

In this example we will combine find with xargs to grep for our string with multiple filenames. Syntax to use with single filename:

find PATH -type f -name <filename> | xargs grep [args] [pattern]

Alternate Method:

find PATH -type f -name <filename> -print0 xargs -0 grep [args] [pattern]

Syntax to use with multiple filenames:

find PATH -type f \( -name <filename-1> -o -name <filename-2> \) | xargs grep [args] [pattern]

So below example can be used to search for all filenames matching "lvm" and "linux" and grep for "test" string

# find /tmp/ \( -name "*linux*" -o -name "*lvm*" \)  -type f | xargs grep -w test

OR

# find /tmp/ \( -name "*linux*" -o -name "*lvm*" \)  -type f -print0 | xargs -0 grep -w test

 

Find with xargs to search recursively
Find with xargs to search recursively

NOTE:

With find we don't need to use -r or --recursive with grep as by default find will search inside all sub-directories

 

Method 3: Using grep with --include

We need not be dependent on third tool to search for a string in some specific file, grep itself has an option to search for only provided files.

--include=GLOB
        Search only files whose base name matches GLOB (using wildcard matching as described under --exclude).

The syntax to use grep recursively with --include would be:

grep -r --include=GLOB PATTERN PATH

We can use --include multiple times to specify multiple filenames with grep.

# grep --include=*lvm* --include=*linux* -rw test /tmp/dir

 

grep recursively with --include
grep recursively with --include

 

4. Grep for string by excluding pre-defined files

Now similar to our last section, we will use find and other tools to exclude certain pre-defined filenames while trying to grep recursively any pattern or string. In the below examples we will "Search for test string in all files except the files that contains lvm and linux in the filename"

 

Method 1: using find with exec (NOT operator)

In this example we will use find command to exclude certain files while grepping for a string by using NOT (!) operator. The general syntax to use this method would be:

find PATH -type f ! -name <filename-1> ! -name <filename-2> -exec grep [args] [pattern] {} +

In this you can provide multiple files to exclude in your search.

# find /tmp/  ! -name "*linux*" ! -name "*lvm*" -type f -exec grep -w test {} +

 

find exec with NOT operator to exclude files
find exec with NOT operator to exclude files

As you see we have used NOT (!) operator with some regex to exclude all filenames with "linux" and "lvm" in their name.

 

Method 2: using find with exec (prune)

We can also use find with exec using "prune" to exclude certain files while grepping for some pattern. The general syntax to use this command would be:

find PATH \( -name <filename-1> -o -name <filename-2> \) -prune -o -type f -exec grep [args] [pattern] {} +

Now we can use this syntax into our example. This will print the file name and the grepped PATTERN

find /tmp/ \( -name "*linux*" -o -name "*lvm*" \) -prune -o -type f -exec grep -w test {} +

 

find exec with prune to exclude files-1
find exec with prune to exclude files-1

OR you can also use grep -H argument to display the filename:

# find /tmp/ \( -name "*linux*" -o -name "*lvm*" \) -prune -o -type f -exec grep -wH test {} \;

 

find exec with prune to exclude files-2
find exec with prune to exclude files-2

If you do not wish to have the filename then you can use:

# find /tmp/ \( -name "*linux*" -o -name "*lvm*" \) -prune -o -type f -exec grep -w test {} \;

 

find exec with prune to exclude files-3
find exec with prune to exclude files-3

 

Method 3: using find with xargs (NOT operator)

Now similar to find with exec, we can also use the same NOT(!) operator with xargs. The general syntax here would be:

find PATH -type f ! -name <filename-1> ! -name <filename-2> | xargs grep [args] [pattern]

Alternate Method:

find PATH -type f ! -name <filename-1> ! -name <filename-2> -print0 xargs -0 grep [args] [pattern]

Now we will adapt this syntax into our example to grep recursively with find command:

# find /tmp/  ! -name "*linux*" ! -name "*lvm*" -type f  -print0 | xargs -0 grep -w test

 

find xargs with NOT operator to exclude files
find xargs with NOT operator to exclude files-1

OR

# find /tmp/  ! -name "*linux*" ! -name "*lvm*" -type f  | xargs  grep -w test

 

find xargs with NOT operator to exclude files-2
find xargs with NOT operator to exclude files-2

 

Method 4: using find with xargs (prune)

Again similar to find with exec, we can use find with xargs combined with prune to exclude certain files. The syntax to achieve this would be:

find PATH -type f \( -name <filename-1> -o -name <filename-2> \) -prune -o -print0 | xargs -0 grep [args] [pattern]

Let us use this syntax in our example:

# find /tmp/ \( -name "*linux*" -o -name "*lvm*" \) -prune -o -type f -print0 | xargs -0  grep -w test

 

find xargs with prune to exclude files
find xargs with prune to exclude files

 

Method 5: Use grep with --exclude

Now all these above methods can be little complicated for beginners so don't worry, we have a supported argument with grep i.e. --exclude=GLOB using which you can exclude certain files when grep is searching for your pattern inside directories and sub-directories. The syntax to use this would be:

grep -r --exclude=GLOB PATTERN PATH

Here you can replace GLOB with the regex or the actual filename of the file which you wish to exclude. You can use --exclude=GLOB multiple times to exclude multiple files

So we can achieve our results using below example without the need of find command:

# grep -r --exclude="*lvm*" --exclude="*linux*" test /tmp/dir/

 

grep recursive with --exclude
grep recursive with --exclude

 

5. Grep for multiple patterns with recursive search

There can be two possible scenarios here

  1. grep for multiple strings inside all directories and sub-directories
  2. grep for multiple strings inside same file

Since this tutorial is more about grep recursive, the first question is relative to this tutorial but I will cover both of them.

 

Example 1: Grep multiple patterns inside directories and sub-directories

With grep we can use -e PATTERN to define multiple patterns at once. The syntax for the same would be:

grep [args] PATH -e PATTERN-1 -e PATTERN-2 ..

For example, I wish to grep for pattern "lvm" and "test" inside all files under /tmp/dir and sub-directories

# grep -rw '/tmp/dir/' -e test -e lvm

 

grep multiple pattern
grep multiple pattern recursively

Similarly you can add -e PATTERN for as many patterns you have to grep recursively.

 

Example 2: Grep for multiple strings in single file

We can use the same syntax with -e PATTERN to grep for multiple strings in the same file. Just instead of providing the directory location, provide the name of the file:

# grep -e "lvm" -e "test" lvm.conf

OR

# grep "lvm\|test" lvm.conf

To also print the filename use -H or --with-filename along with grep as shown below:

# grep -H "lvm\|test" lvm.conf

 

6. Grep recursively for files with symbolic links

By default grep ignores looking into symbolic link files and only searches in text file format. To overcome this, i.e. to make sure grep also looks into symbolic links while searching for string

-R, --dereference-recursive
      Read all files under each directory, recursively.  Follow all symbolic links, unlike -r.

The syntax to use for this example:

grep -R PATTERN PATH

 

Example 1: Grep for "test" string under any symlinks and file under /tmp/dir

To achieve this we will use:

# grep -R test /tmp/dir/

 

grep for symbolic link files
grep in files and symbolic links

 

Conclusion

In this tutorial we learned that grep itself has an argument to perform recursive search for any pattern or string. You can use -r to grep recursively inside all directories and sub-directories or use -R to also include symlinks in your search (which is excluded with -r). Alternatively we have find command which can be combined with normal grep to search inside all directories and sub-directories, which also allows us to include and exclude certain files and directories from the search.

This tutorial is all about grep but I have also tried to give some overview on usage of find with grep, now find is a very versatile tool, we can add a lot of options to filter your search such as -maxdepth to limit the number of sub-directories to search and many more.

Lastly I hope the steps from the article to perform grep recursively with multiple scenarios and examples on Linux was helpful. So, let me know your suggestions and feedback using the comment section.

You can read more

Leave a Comment

Please use shortcodes <pre class=comments>your code</pre> for syntax highlighting when adding code.