tags:

views:

826

answers:

7

I would like to find the files containing specific string under linux. I tried something like but could not succeed:

find . -name *.txt | egrep mystring

+2  A: 

try:

find . -name '*.txt' | xargs egrep mystring

There are two problems with your version:

Firstly, *.txt will first be expanded by the shell, giving you a listing of files in the current directory which end in .txt, so for instance, if you have the following:

[dsm@localhost:~]$ ls *.txt
test.txt
[dsm@localhost:~]$

your find command will turn into find . -name test.txt. Just try the following to illustrate:

[dsm@localhost:~]$ echo find . -name *.txt
find . -name test.txt
[dsm@localhost:~]$

Secondly, egrep does not take filenames from STDIN. To convert them to arguments you need to use xargs

dsm
I would also suggest enclosing the pattern following -name in quotes to prevent the shell from doing pattern matching on it
Peter van der Heijden
I would like to thank all of you providing such comprehensive answers.
Tolga
+4  A: 

Here you are sending the file names (output of the find command) as input to egrep; you actually want to run egrep on the contents of the files.

Here are a couple of alternatives:

find . -name "*.txt" -exec egrep mystring {} \;

or even better

find . -name "*.txt" -print0 | xargs -0 egrep mystring

Check the find command help to check what the single arguments do.
The first approach will spawn a new process for every file, while the second will pass more than one file as argument to egrep; the -print0 and -0 flags are needed to deal with potentially nasty file names (allowing to separate file names correctly even if a file name contains a space, for example).

Paolo Tedesco
You are missing `\+` or `\;` at the end of your first command.
spatz
Does't this attempt to find the filename within mystring? I think he's looking for the other way around.
Kevin
@spatz: thanks for the remark, I fixed the example.
Paolo Tedesco
@Kevin: yes, you're right. Fixed it, thanks :)
Paolo Tedesco
@spatz: handy feature about \+ is that + is not a special character to most shells (I don't know of any shells where it is special, but am reluctant to say all), so you don't need the backslash.
William Pursell
+1  A: 
find . -name *.txt | egrep mystring

That will not work as egrep will be searching for mystring within the output generated by find . -name *.txt which are just the path to *.txt files.

Instead, you can use xargs:

find . -name *.txt | xargs egrep mystring
Alan Haggai Alavi
+1  A: 

You could use

find . -iname *.txt -exec egrep mystring \{\} \;
Wienczny
+1  A: 

Here's an example that will return the file paths of a all *.log files that have a line that begins with ERROR:

find . -name "*.log" -exec egrep -l '^ERROR' {} \;
Kevin
A: 

there's a recursive option from egrep you can use

egrep -R "pattern" *.log
ghostdog74
This does not work. The -R option only recurses into directories if they are supplied in the argument list. In which case all files in those directories will be read not only files ending in .log. If you have any success with this method it is because there are files ending in .log in the current directory because then the shell parses the *.log.
Peter van der Heijden
A: 

If you only want the filenames:

find . -type f -name '*.txt' -exec egrep -l pattern {} \;

If you want filenames and matches:

find . -type f -name '*.txt' -exec egrep pattern {} /dev/null \;
wallenborn