12

how do I find a phrase/word recursively in a file tree in Linux?
I tried find . -name ./* | grep my_phrase and I tried grep -r "register_long_arrays" *

2
  • 3
    are you looking for files whose name contains that phrase/word or for files whose contents contains it? Aug 31, 2010 at 13:59
  • @Nathan Fellman The content contains the phrase Sep 7, 2010 at 13:52

6 Answers 6

15
grep -r "register_long_arrays" *

will recursively find all occurrences of register_long_arrays in your current directory.

If you want to combine find with grep to limit the types of files searched you should use it like this (this example will limit the search to files ending .txt):

find . -name '*.txt' -exec grep "register_long_arrays" {} \;

The {} is replaced with every file that find finds without you having to worry about escaping problem characters like spaces. Note the backslash before the semicolon. This ensures that the semicolon is escaped and passed to the exec clause (grep) rather than terminating the find command.

If you're still not finding what you want it may be a case issue, (supply the -i flag to grep to ignore case) or perhaps the content you want is in a hidden file (starting with .), which * will not match, in which case supply both * and .* as arguments to grep.

1
  • 2
    Your find ... -exec grep command will not display the filename(s) of the files that contain the string, because grep is being called with a single filename each time. I suggest using xargs to invoke grep for efficiency (see some other responses). Even with xargs, it's possible that grep will only be invoked with a single filename, so use the old sk00l idiom xargs grep register_long_arrays /dev/null to trick grep, or use grep -H (a GNU-ism).
    – coneslayer
    Aug 31, 2010 at 17:12
4
find . -type f -exec grep my_phrase {} \;

will work to search all regular files, but it invokes grep once for every file. This is inefficient and will make the search take noticeably longer on slow computers and/or large directory hierarchies. For that reason, it is better to use xargs:

find . -type f | xargs grep my_phrase

or, if you have files whose names contain spaces,

find . -type f -print0 | xargs -0 grep my_phrase

Even simpler is to just use the -r option to grep:

grep -r my_phrase .

Note the use of . rather than * as the file name argument. That avoids the problem of the expansion of * not including hidden files.

1
  • Put quotes around the file name placeholder '{}' to handle file names that contain spaces. Dec 15, 2019 at 3:59
0

try:

find . -name ./\* | xargs grep my_phrase

xargs will call grep with on each of the files that find finds.

0

You can also try ack. It's fast. If you work with trees of code it's great tool.

Searching for foobar in file contents recursively from current directory:

ack foobar

Searching for files which names match regexp:

ack -g "foo(bar)?"
0
find . -exec grep my_phrase {} \;

find generates a list of all files at or below current directory. exec will execute the command grep my_phrase for each file found. The \; is just magic to make it work. Details of how it works can usually be seen with man find.

You might also want to look at the -H option of grep if you want to know not just if it was found but where.

0

I define a function in my .bashrc file that provides the functionality of most all the other answers:

findgrep() {                                                                                                                
    if [[ $# == 1 ]]; then                                                                                                      
        find . -type f -exec grep -H "$1" '{}' \;                                                                           
    elif [[ $# == 2 ]]; then                                                                                                    
        find $1 -type f -exec grep -H "$2" '{}' \;                                                                          
    elif [[ $# == 3 ]]; then                                                                                                    
        find $1 -type f -name "$2" -exec grep -H "$3" '{}' \;                                                               
    else                                                                                                                        
        echo 'Usage:'                                                                                                           
        echo 'findgrep searchString'                                                                                            
        echo 'findgrep startDir searchString'                                                                                   
        echo 'findgrep startDir "fileNamePattern" searchString'                                                             
    fi                                                                                                                  
}

You can specify just the regular expression, or restrict the search with more arguments:

  • Just a regular expression
  • A starting directory and regular expression
  • A starting directory, file name pattern and regular expression
  • If you specify no arguments or too many arguments, it prints a help message

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .