Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

How do I search files, some of which might be directories (in this case recursively) for a given string?

I'd like to search source files for a class definition, so it would also be great if there was the name of the containing file before each output string.

share|improve this question
    
May I ask why would you need that? –  Anonymous Jun 29 '09 at 13:09
    
I'm searching source files for a method definition. –  Alex Jul 1 '09 at 17:40
add comment

9 Answers

up vote 6 down vote accepted

You could use grep:

grep -rn 'classname' /path/to/source

This will also print the line number next to each match.

Case insensitive:

grep -rin 'classname' /path/to/source

Search non-recursively in all cpp files:

grep -n 'classname' /path/to/source/*.cpp
share|improve this answer
add comment

All the above answers will work perfectly well, but may cause false positives if you've got the string in more than just source code. Say you are looking for where you use the FooBar class in a java project, you can search for all files named *.java and grep just those.

# grep "FooBar" -Hn $(find -name "*.java")

The section in between the $() will expand to the output of that command. The -H prints out the filename. It's the default where there is more than one file name, but we explicitly add it here in case the expansion only returns one file name. The -n prints the line number of the match.

This will work for small projects, but if you're dealing with a larger project, there the potential for the find to expand to a string longer than the command line limit. It's therefore safer to use:

# find -name "*.java" -print0 | xargs -0 grep "FooBar" -Hn

xargs will take input from standard in and split it up so it fits on the command line, running the command multiple times if necessary. The -print0 and -0 are required to deal with files with spaces in their name.

You can also look for all the filesnames with a match in using:

# find -name "*.java" -print0 | xargs -0 grep "FooBar" -l

The -l will just display the file name and stop looking in a particular file as soon as it finds a match.

If you're going to be doing this sort of thing frequently, you may want to look at a tool like ctags or exuberant tags, which maintain a search index of your source code and can answer these sorts of questions quickly. Both vim and emacs have support for these tools. You may also like to look at an IDE like eclipse, which can do cross referencing very well.

(I know you were looking for a class definition, but in Java a class will be defined in a file with the same name as the class. If you were doing cpp, you could do something like:

# find -name "*.cpp" -o -name "*.cc" -o -name "*.h" -o -name "*.hpp" -print0 | \
  xargs -0 egrep "class\s+FooBar" -Hn
share|improve this answer
    
Very comprehensive answer. –  nickd Sep 23 '10 at 21:20
add comment

For searching through source code, I've found that ack (betterthangrep.com) is, to quote the marketing, better than grep. Its output is easier to read and it will do a lot of stuff automagically, like ignoring non-source code files: VCS directories (eg CVS and .svn), backup files.

share|improve this answer
add comment

ack is better for searching source codes as it already recognize some of the most popular file extension (c, perl, etc). It's as fast as grep and by default ignoring all your version control artifact. For example if you want to search some pattern perl source code you could use

ack --perl pattern

instead of

grep pattern $(find . -name '*.pl' -or -name '*.pm' -or -name '*.pod' | grep -v .svn)
share|improve this answer
add comment
grep -r string *

finds all files containing the characters "string" in all (non-hidden) files in the current directory and all sub-directories recursively. You can use the usual regexes to tune the string. See the grep info/man pages for more options.

share|improve this answer
add comment

Already answered (I think this is what you are looking for) on this serverfault post:

http://serverfault.com/questions/9822/recursive-text-search-with-grep-and-file-patterns/9832#9832

share|improve this answer
add comment

this is something I find myself using alot so I have put two bash functions in my .bashrc
First one does a recursive search for text in filenames.
Second one will do a recursive search for text inside of files returning the filenames of the files that match.

ff () {
        find . -name "*$@*" -print; 
}


fff () {
    find . -type f -print0 | xargs -0 grep -l $@
}

example usage:

[lunix@godzilla ~/tmp]$ ff foo
./slideshow/foo
./slideshow/velocity_puppet_workshop_2009/repo/modules/foo

[lunix@godzilla ~/tmp/test]$ fff  commodo
./file2
[lunix@godzilla ~/tmp/test]$ ll
total 16K
drwxr-xr-x 2 lunix lunix 4.0K 2009-06-29 23:01 .
drwxr-xr-x 4 lunix lunix 4.0K 2009-06-29 22:57 ..
-rw-r--r-- 1 lunix lunix 1.3K 2009-06-29 22:59 file1
-rw-r--r-- 1 lunix lunix 1.7K 2009-06-29 23:00 file2
share|improve this answer
add comment

This classical find + exec could also be handy:

find /path/to/ -type f -exec grep -i 'string' {} \;
share|improve this answer
add comment

grep -rn * it will work !!

share|improve this answer
2  
Why are you yelling? –  Telemachus Jun 29 '09 at 11:43
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.