Linux / UNIX Recursively Search All Files For A String

How do I recursively search all text files for a string such as foo under UNIX / Linux / *BSD / Mac OS X shell prompt?

You can use grep command or find command as follows to search all files for a string or words recursively.
Tutorial details
Difficulty level Easy
Root privileges No
Requirements Linux or Unix with grep and find utilities
Est. reading time 2 minutes

How to use grep command to recursively search All files for a String

The syntax is as follows for the grep command to find all files under Linux or Unix in the current directory:
cd /path/to/dir
grep -r "word" .
grep -r "string" .

The -r option read/sarch all files under each directory, recursively, following symbolic links only if they are on the command line. In other words, it will look into sub-directories too. We can also state path as follows:
grep -r 'something' /path/to/dir

Following symtlinks

The following syntax will read and search all files under each directory, recursively. Follow all symbolic links too by passing the -R (capital R):
grep -R 'word' .
grep -R 'string-to-search' /path/to/dir/

Case sensitive recursive search

To ignore case distinctions, try:
grep -ri "word" .

Displaying files name when searching for a string/word

To display print only the filenames with GNU grep, enter:
grep -r -l "foo" .
You can also specify directory name:
grep -r -l "foo" /path/to/dir/*.c

Using find command to search recursively

find command is recommend because of speed and ability to deal with filenames that contain spaces.

cd /path/to/dir
find . -type f -exec grep -l "word" {} +
find . -type f -exec grep -l "seting" {} +
find . -type f -exec grep -l "foo" {} +
find /search/dir/ -type f -name "*.c" -print0 | xargs -I {} -0 grep "foo" "{}"
 
## Search /etc/ directory for 'nameserver' word in all *.conf files ##
find /etc/ -type f -name "*.conf" -print0 | xargs -I {} -0 grep "nameserver" "{}"

Older UNIX version should use xargs to speed up things:
find /path/to/dir -type f | xargs grep -l "foo"
It is good idea to pass -print0 option to find command that it can deal with filenames that contain spaces or other metacharacters:
find /path/to/dir -type f -print0 | xargs -0 grep -l "foo"
OR use the following OSX/BSD/find or GNU/find example:

find /path/to/dir/ -type f -name "file-pattern" -print0 | xargs -I {}  -0 grep -l "search-term" "{}"
 
## OR ##
find /mycool/project/ -type f -name "*.py" -print0 | xargs -I {}  -0 grep -H --color "methodNameHere" "{}"
 
## OR search all files in /etc/ dir for 'nameserver' word ##
find /etc/ -iname "*" -type f -print0  |  xargs -0 grep -H "nameserver"

Sample outputs from the last command:

Fig.01: Unix and Linux: How to Grep Recursively?

Finding all files containing specific text on Linux

Say you want to find orange and mango words, then try:
grep -r -E 'orange|mango' .
grep -r -E 'orange|mango' /dir/to/search/

This is how you set up pattern
grep -r -e ‘pattern’ /dir/to/search
For extended grep (see egrep command for regular expressions):
egrep -r 'word' /dir/to/search/
egrep -r 'regex' /dir/to/search/

We can combine all options too:
grep -rnw -e 'pattern' /dir/to/search/
egrep -rnw 'regex' /path/to/search/

How to search only files that have specific extensions

Want to search files having either ‘.pl’ or ‘.php’ extensions for foo()? Try:
grep --include=\*.{php,pl} -rnw "foo()" /dir/to/search/
egrep --include=\*.{php,pl} -rnw "regex" /dir/to/search/

We can skip any command-line file with a name suffix that matches the pattern GLOB, using wildcard matching. For instance, exclude all .bin files:
grep --exclude=\*.bin -r -n -0 'string_to_search' /path/
egrep --exclude=\*.bin -r -n -0 'regex' /path/to/search/

When searching recursively, we can skip any subdirectory whose base name matches wildcard. For instance, skip includes and docs directory:

grep --exclude-dir={includes,docs} -r 'string_text_to_search' /dir/
grep --exclude-dir={includes,docs} -r -w -n 'string_text_to_search' /dir/
egrep --exclude-dir={includes,docs} -r -w -n 'regex' /dir/

Understanding grep command options that used for searching text files

  • -r : Rrecursive search
  • -i : Ignore case distinctions in patterns and data
  • -w : Match only whole words
  • -n : Show line number with output lines
  • -e 'pattern' : Use PATTERNS for matching
  • -E : All search PATTERNS are extended regular expressions
  • --include=GLOB : Search only files that match GLOB (a file pattern)
  • --exclude=GLOB : Skip files that match GLOB
  • --exclude-dir=GLOB : Skip directories that match GLOB

GLOB means to expand to wildcard patterns. For example, GLOB, *.txt means all files ending with .txt extension. A string is a wildcard pattern if it contains one of the following characters:

  1. ? – Matches any single character.
  2. * – Matches any string, including the empty string.
  3. [

Globbing is the operation that expands a wildcard pattern into the list of path-names matching the pattern.

Summing up

You learned how to search for text, string, or words recursively on Linux, macOS, *BSD, and Unix-like systems. See the following man pages:
man grep
man find
man 3 glob
man 7 glob


🐧 Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

🐧 22 comments so far... add one


CategoryList of Unix and Linux commands
Disk space analyzersdf ncdu pydf
File Managementcat cp mkdir tree
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network UtilitiesNetHogs dig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
22 comments… add one
  • rjbcollege May 27, 2010 @ 10:08

    That is fantastic, a command that says it does exactly what I’m looking for.

    Unfortunately, when I copy and paste the example to recursivle search for files containing a string:
    find . -type f -exec grep -l “word” {} +

    in to my linux session I get a set of error message lines which all say this:

    find: grep: Argument list too long

    To fix this, simply add the following to hide any such error messages by oplacing them in the trash:

    find . -type f -exec grep -l “word” {} + 2>>/dev/null

  • Pete Shore Jul 25, 2010 @ 10:51

    Perfect, had to search a joomla install for all occurrences of a string, used grep as i remember if from my uni days, thanks for the post.

    Pete

  • lanh May 14, 2011 @ 17:37

    Thank you this was very useful for debugging!

  • Radhakrishnan Jul 12, 2011 @ 7:06

    This tutorial is very useful .

  • Fernando Lopez Jr. Oct 2, 2011 @ 1:24

    it won’t work if you are trying to search for:

    grep -r “test!!!” .

    you need to use the single quotations. like:

    grep -r ‘test!!!’ .

  • jinil Feb 15, 2012 @ 4:51

    How can I recursively search all files for 2 strings?
    I mean, files containing both strings..

    Thanks :)

    • Ben May 17, 2015 @ 0:28

      You can pipe one grep into another.

    • bob Oct 8, 2016 @ 21:13

      grep -r -e string1 -e string2 /

  • analytical Feb 21, 2012 @ 15:28

    Thanks, changed my default web directory somewhere and now I don’t know where. This will help.

  • mica Mar 30, 2012 @ 15:40

    Would you let me know how to add a grep -v to the search , so i can supress some unwanted files?

    thanks

    • bob Oct 8, 2016 @ 21:21

      find . -not -name “*.svn” -not -name “*.git -exec grep -e string1 -e string2 {} \;

  • Ken Apr 6, 2012 @ 22:17

    This is indeed great. Now I wanted to shortcut this expression by putting it into my .bash_profile file as an alias but I can’t get that too work. I’ve tried a lot of variations on this theme:

    alias f=”find . -type f -exec grep -l $1 {} +”

    but then when I type something like “f foobar” it responds with “find: foobar: unknown option”. I’m sure this is stupidly easy but I’ve tried enough variations I thought I’d ask for some help.

    • 🐧 nixCraft Apr 7, 2012 @ 10:24

      You can not pass args to alias. Use bash shell function:

      f(){ find . -type f -exec grep -l $1 {} + ; }
      

      Run it as:

      f foobar

      Hope this helps!

  • Ken Apr 10, 2012 @ 16:55

    Great thanks Vivek!

  • Arsie May 28, 2012 @ 3:23

    Thanks for this information, I was able to get the file I am looking for on my box.

  • CaptSaltyJack May 14, 2013 @ 3:29

    Actually, using find to grep files is way slower than using grep -r. Try it, go into a folder with a whole bunch of files (hundreds, if not more), and run:

    date ; find . -type f -exec grep somestring {} \; ; date

    and then:

    date ; grep -r somestring . ; date

    The first operation took me about 10 seconds. The second one took about 3-4 seconds.

  • perfect tutorial Feb 26, 2014 @ 5:01

    Great article! Just another reason why *nix should be embraced for ever.

  • Joshua Pinter Mar 21, 2014 @ 19:44

    Also, it’s helpful to use the “-n” flag to show the line number of the file the text is on.

  • Igor Sep 24, 2015 @ 19:38

    Awesome!
    grep -ri “word” .
    grep -ri -l “word” .
    thanks a lot.

  • Ranjeet Jan 20, 2016 @ 8:45

    Thank you very much for this find command

  • tpro Oct 8, 2016 @ 16:16

    Definitely better and faster tool is ack-grep package

  • Jon Oct 8, 2016 @ 17:40

    How can the command be modified to search sub folders as well?

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre> for code samples. Still have questions? Post it on our forum