There must be a better / shorter way to do this:
# Find files that contain <string-to-find> in current directory
# (including sub directories)
$ find . | xargs grep <string-to-find>
Also, to search only e.g. HTML files:
# find . | grep html$ | xargs grep <string-to-find>
Thanks beforehand!
The grep command searches through the file, looking for matches to the pattern specified. To use it type grep , then the pattern we're searching for and finally the name of the file (or files) we're searching in. The output is the three lines in the file that contain the letters 'not'.
What is the difference between the grep and find commands? Find is a utility to search for files and directories in the Linux filesystem based on certain criteria (e.g. filename, modify date, size, file type, etc…), grep is a utility to search for patterns in the content of files or in the output of other commands.
Is fast grep faster? The grep utility searches text files for regular expressions, but it can search for ordinary strings since these strings are a special case of regular expressions. However, if your regular expressions are in fact simply text strings, fgrep may be much faster than grep .
find . -name \*.html
or, if you want to find files with names matching a regular expression:
find . -regex filename-regex.\*\.html
or, if you want to search for a regular expression in files with names matching a regular expression
find . -regex filename-regex.\*\.html -exec grep -H string-to-find {} \;
The grep
argument -H
outputs the name of the file, if that's of interest. If not, you can safely remove it and simply use grep
. This will instruct find
to execute grep string-to-find filename
for each file name it finds, thus avoiding the possibility of the list of arguments being too long, and the need for find
to finish executing before it can pass its results to xargs
.
To address your examples:
find . | xargs grep <string-to-find>
could be replaced with
find . -exec grep -H string-to-find {} \;
and
find . | grep html$ | xargs grep <string-to-find>
could be replaced with
find . -name \*.html -exec grep -H string-to-find {} \;
Not sure what do you mean by better, my first thought was something like this:
grep <string-to-find> $(find -regex .*\.html)
But that's worse because result of the find would be accumulated somewhere in shells memory and then sent as a huge chunk of input arguments
The only imporvement I see too your suggestion is
find -regex .*\.html | xargs grep <string-to-find>
That way find performs all the filtering and you still retain piped processing
If this is going to be a common search utility you're going to utilize, you may want to take a look at ack, which combines both the find
and the grep
together into this functionality that you're looking for. It has fewer features than grep
, though 99% of my searches are suited perfectly by replacing all instances of grep
with ack
.
Besides the other answers given, I also suggest this construct:
Even better, if the filenames have spaces in them, you can either quote
find . -type f -name "*.html" -print|xargs -I FILENAME grep "< string-to-find>" FILENAME
"FILENAME"
or pass a null-terminated (instead of newline-terminated) result from find
to xargs
, and then have xargs
strip those out itself:
find . -type f -name "*.html" -print0|xargs -0 -I FILENAME grep "< string-to-find>" FILENAME
here --^ and --^
Here, the name FILENAME
can actually be anything, but it needs to match both
Like this:
find . -type f -name "*.html" -print0|xargs -0 -I FILENAME grep "< string-to-find>" FILENAME
here --^ and --^
find . -type f -name "*.html" -print0|xargs -0 -I GRRRR grep "< string-to-find>" GRRR
this --^ this --^
It's essentially doing the same thing as the {}
used within the find
statement itself to state "the line of text that this returned". Otherwise, xargs just tacks the results of find
to the END of all the rest of the commands you give it (which doesn't help much if you want grep
to search inside a file, which is usually specified last on the command-line).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With