Searching a number of files for a string in LInux

Solution 1:

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

Solution 2:

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 

Solution 3:

For searching through source code, I've found that ack ( 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.

Solution 4:

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)