1861
votes

How do I recursively grep all directories and subdirectories?

find . | xargs grep "texthere" *
26
@TC1 The sad thing is that grep itself can answer the question (at least GNU grep): grep --help |grep recursiveFrank Schmitt
If you find yourself frequently using grep to do recursive searches (especially if you manually do a lot of file/directory exlusions), you may find ack (a very programmer-friendly grep alternative) useful.Nick McCurdy
Actually neither -r nor --recursive work on the Solaris box I use at work. And the man page for grep doesn't mention anything recursive. I had to resort to find and xargs myself.Ben
ag is my favorite way to do this now github.com/ggreer/the_silver_searcherdranxo
grep -rin xlsx *.pl doesn't work for me on Redhat Linux. I get a "no match" error.Bulrush

26 Answers

2743
votes
grep -r "texthere" .

The first parameter represents the regular expression to search for, while the second one represents the directory that should be searched. In this case, . means the current directory.

Note: This works for GNU grep, and on some platforms like Solaris you must specifically use GNU grep as opposed to legacy implementation. For Solaris this is the ggrep command.

744
votes

If you know the extension or pattern of the file you would like, another method is to use --include option:

grep -r --include "*.txt" texthere .

You can also mention files to exclude with --exclude.

Ag

If you frequently search through code, Ag (The Silver Searcher) is a much faster alternative to grep, that's customized for searching code. For instance, it's recursive by default and automatically ignores files and directories listed in .gitignore, so you don't have to keep passing the same cumbersome exclude options to grep or find.

133
votes

Also:

find ./ -type f -print0 | xargs -0 grep "foo"

but grep -r is a better answer.

129
votes

I now always use (even on Windows with GoW -- Gnu on Windows):

grep --include="*.xxx" -nRHI "my Text to grep" *

(As noted by kronen in the comments, you can add 2>/dev/null to void permission denied outputs)

That includes the following options:

--include=PATTERN

Recurse in directories only searching file matching PATTERN.

-n, --line-number

Prefix each line of output with the line number within its input file.

(Note: phuclv adds in the comments that -n decreases performance a lot so, so you might want to skip that option)

-R, -r, --recursive

Read all files under each directory, recursively; this is equivalent to the -d recurse option.

-H, --with-filename

Print the filename for each match.

-I     

Process a binary file as if it did not contain matching data;
this is equivalent to the --binary-files=without-match option.

And I can add 'i' (-nRHIi), if I want case-insensitive results.

I can get:

/home/vonc/gitpoc/passenger/gitlist/github #grep --include="*.php" -nRHI "hidden" *
src/GitList/Application.php:43:            'git.hidden'      => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
src/GitList/Provider/GitServiceProvider.php:21:            $options['hidden'] = $app['git.hidden'];
tests/InterfaceTest.php:32:        $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
vendor/klaussilveira/gitter/lib/Gitter/Client.php:20:    protected $hidden;
vendor/klaussilveira/gitter/lib/Gitter/Client.php:170:     * Get hidden repository list
vendor/klaussilveira/gitter/lib/Gitter/Client.php:176:        return $this->hidden;
...
25
votes

In POSIX systems, you don't find -r parameter for grep and your grep -rn "stuff" . won't run, but if you use find command it will:

find . -type f -exec grep -n "stuff" {} \; -print

Agreed by Solaris and HP-UX.

22
votes

globbing **

Using grep -r works, but it may overkill, especially in large folders.

For more practical usage, here is the syntax which uses globbing syntax (**):

grep "texthere" **/*.txt

which greps only specific files with pattern selected pattern. It works for supported shells such as Bash +4 or zsh.

To activate this feature, run: shopt -s globstar.

See also: How do I find all files containing specific text on Linux?

git grep

For projects under Git version control, use:

git grep "pattern"

which is much quicker.

ripgrep

For larger projects, the quickest grepping tool is ripgrep which greps files recursively by default:

rg "pattern" .

It's built on top of Rust's regex engine which uses finite automata, SIMD and aggressive literal optimizations to make searching very fast. Check the detailed analysis here.

11
votes

To find name of files with path recursively containing the particular string use below command for UNIX:

find . | xargs grep "searched-string"

for Linux:

grep -r "searched-string" .

find a file on UNIX server

find . -type f -name file_name

find a file on LINUX server

find . -name file_name
11
votes

If you only want to follow actual directories, and not symbolic links,

grep -r "thingToBeFound" directory

If you want to follow symbolic links as well as actual directories (be careful of infinite recursion),

grep -R "thing to be found" directory

Since you're trying to grep recursively, the following options may also be useful to you:

-H: outputs the filename with the line

-n: outputs the line number in the file

So if you want to find all files containing Darth Vader in the current directory or any subdirectories and capture the filename and line number, but do not want the recursion to follow symbolic links, the command would be

grep -rnH "Darth Vader" .

If you want to find all mentions of the word cat in the directory

/home/adam/Desktop/TomAndJerry 

and you're currently in the directory

/home/adam/Desktop/WorldDominationPlot

and you want to capture the filename but not the line number of any instance of the string "cats", and you want the recursion to follow symbolic links if it finds them, you could run either of the following

grep -RH "cats" ../TomAndJerry                   #relative directory

grep -RH "cats" /home/adam/Desktop/TomAndJerry   #absolute directory

Source:

running "grep --help"

A short introduction to symbolic links, for anyone reading this answer and confused by my reference to them: https://www.nixtutor.com/freebsd/understanding-symbolic-links/

11
votes

just the filenames can be useful too

grep -r -l "foo" .
8
votes

ag is my favorite way to do this now github.com/ggreer/the_silver_searcher . It's basically the same thing as ack but with a few more optimizations.

Here's a short benchmark. I clear the cache before each test (cf https://askubuntu.com/questions/155768/how-do-i-clean-or-disable-the-memory-cache )

ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time grep -r "hey ya" .

real    0m9.458s
user    0m0.368s
sys 0m3.788s
ryan@3G08:$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ack-grep "hey ya" .

real    0m6.296s
user    0m0.716s
sys 0m1.056s
ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ag "hey ya" .

real    0m5.641s
user    0m0.356s
sys 0m3.444s
ryan@3G08$ time ag "hey ya" . #test without first clearing cache

real    0m0.154s
user    0m0.224s
sys 0m0.172s
6
votes

This should work:

grep -R "texthere" *
6
votes

If you are looking for a specific content in all files from a directory structure, you may use find since it is more clear what you are doing:

find -type f -exec grep -l "texthere" {} +

Note that -l (downcase of L) shows the name of the file that contains the text. Remove it if you instead want to print the match itself. Or use -H to get the file together with the match. All together, other alternatives are:

find -type f -exec grep -Hn "texthere" {} +

Where -n prints the line number.

6
votes

This is the one that worked for my case on my current machine (git bash on windows 7):

find ./ -type f -iname "*.cs" -print0 | xargs -0 grep "content pattern"

I always forget the -print0 and -0 for paths with spaces.

EDIT: My preferred tool is now instead ripgrep: https://github.com/BurntSushi/ripgrep/releases . It's really fast and has better defaults (like recursive by default). Same example as my original answer but using ripgrep: rg -g "*.cs" "content pattern"

4
votes

grep -r "texthere" . (notice period at the end)

(^credit: https://stackoverflow.com/a/1987928/1438029)


Clarification:

grep -r "texthere" / (recursively grep all directories and subdirectories)

grep -r "texthere" . (recursively grep these directories and subdirectories)

grep recursive

grep [options] PATTERN [FILE...]

[options]

-R, -r, --recursive

Read all files under each directory, recursively.

This is equivalent to the -d recurse or --directories=recurse option.

http://linuxcommand.org/man_pages/grep1.html

grep help

$ grep --help

$ grep --help |grep recursive
  -r, --recursive           like --directories=recurse
  -R, --dereference-recursive

Alternatives

ack (http://beyondgrep.com/)

ag (http://github.com/ggreer/the_silver_searcher)

4
votes

In 2018, you want to use ripgrep or the-silver-searcher because they are way faster than the alternatives.

Here is a directory with 336 first-level subdirectories:

% find . -maxdepth 1 -type d | wc -l
     336

% time rg -w aggs -g '*.py'
...
rg -w aggs -g '*.py'  1.24s user 2.23s system 283% cpu 1.222 total

% time ag -w aggs -G '.*py$'
...
ag -w aggs -G '.*py$'  2.71s user 1.55s system 116% cpu 3.651 total

% time find ./ -type f -name '*.py' | xargs grep -w aggs
...
find ./ -type f -name '*.py'  1.34s user 5.68s system 32% cpu 21.329 total
xargs grep -w aggs  6.65s user 0.49s system 32% cpu 22.164 total

On OSX, this installs ripgrep: brew install ripgrep. This installs silver-searcher: brew install the_silver_searcher.

4
votes

Throwing my two cents here. As others already mentioned grep -r doesn't work on every platform. This may sound silly but I always use git.

git grep "texthere"

Even if the directory is not staged, I just stage it and use git grep.

3
votes

In my IBM AIX Server (OS version: AIX 5.2), use:

find ./ -type f -print -exec grep -n -i "stringYouWannaFind" {} \; 

this will print out path/file name and relative line number in the file like:

./inc/xxxx_x.h

2865: /** Description : stringYouWannaFind */

anyway,it works for me : )

3
votes

Below are the command for search a String recursively on Unix and Linux environment.

for UNIX command is:

find . -name "string to be searched" -exec grep "text" "{}" \;

for Linux command is:

grep -r "string to be searched" .
2
votes

For a list of available flags:

grep --help 

Returns all matches for the regexp texthere in the current directory, with the corresponding line number:

grep -rn "texthere" .

Returns all matches for texthere, starting at the root directory, with the corresponding line number and ignoring case:

grep -rni "texthere" /

flags used here:

  • -r recursive
  • -n print line number with output
  • -i ignore case
1
votes

Note that find . -type f | xargs grep whatever sorts of solutions will run into "Argument list to long" errors when there are too many files matched by find.

The best bet is grep -r but if that isn't available, use find . -type f -exec grep -H whatever {} \; instead.

1
votes

I guess this is what you're trying to write

grep myText $(find .)

and this may be something else helpful if you want to find the files grep hit

grep myText $(find .) | cut -d : -f 1 | sort | uniq
0
votes

Just for fun, a quick and dirty search of *.txt files if the @christangrant answer is too much to type :-)

grep -r texthere .|grep .txt

0
votes

Here's a recursive (tested lightly with bash and sh) function that traverses all subfolders of a given folder ($1) and using grep searches for given string ($3) in given files ($2):

$ cat script.sh
#!/bin/sh

cd "$1"

loop () {
    for i in *
    do
        if [ -d "$i" ]
        then
            # echo entering "$i"
            cd "$i"
            loop "$1" "$2"
        fi
    done

    if [ -f "$1" ]
    then
        grep -l "$2" "$PWD/$1"
    fi

    cd ..
}

loop "$2" "$3"

Running it and an example output:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename
0
votes

For .gz files, recursively scan all files and directories Change file type or put *

find . -name \*.gz -print0 | xargs -0 zgrep "STRING"
0
votes

another syntax to grep a string in all files on a Linux system recursively

grep -irn "string" /

displays massive result so u might need to filter the output by piping

-2
votes
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .