tags:

views:

2854

answers:

7

Hi, I am doing a find and then getting a list of files. how do I pipe it to another utility like cat (so that cat displays the contents of all those files) and basically need to grep something from these files.

A: 

Sounds like a job for a shell script to me:

for file in 'find -name *.xml'
do
   grep 'hello' file
done

or something like that

Gandalf
This is a valid, though not necessarily optimal, answer to the question.
Jonathan Leffler
+5  A: 
find . -print | xargs grep something

If you're on Linux or have the GNU find and xargs, then use -print0 with find and -0 with xargs to handle file names containing spaces and other odd-ball characters.

If you don't want the file names - just the text - then add an appropriate option to grep (usually -h to suppressing 'headings'). To absolutely guarantee the file name is printed by grep (even if only one file is found, or the last invocation of grep is only given 1 file name), then add /dev/null to the xargs command line, so that there will always be at least two file names.

Jonathan Leffler
A: 

The find command has an -exec argument that you can use for things like this, you could just do the grep directly using that.

For example (from here, other good examples at this page):

find . -exec grep "www.athabasca" '{}' \; -print
Chad Birch
A: 

Are you trying to find text in files? You can simply use grep for that...

grep searchterm *
Scott Anderson
A: 

There are a few ways to do this. The simplest is to use backticks:

cat `find [whatever]`

(you can also use $() instead of backticks in some shells, including bash)

This takes the output of find and puts it on cat's command-line. It doesn't work if find has too much output (more than can fit on a command-line) or if the output has special characters (or spaces).

You can also use find's -exec action, which executes a command for each file it finds:

find [whatever] -exec cat {} \;

This will run cat once for every single file (rather than running a single instance of cat passing it multiple filenames) which can be inefficient and might not have the behavior you want for some commands (though it's fine for cat). The syntax is also a bit annoying. (You need to escape the semicolon because semicolon is special to the shell!)

You can also use xargs:

find [whatever] | xargs cat

xargs runs the command specified (cat, in this case), and adds arguments based on what it reads from stdin.

This will break up the command-line if necessary. That is, if find produces too much output, it'll run cat multiple times. (like the note about -exec earlier, there are some commands where this splitting may result in different behavior) It still has issues with spaces in filenames as xargs just uses whitespace as a delimiter.

The most robust method is this:

find [whatever] -print0 | xargs -0 cat

The -print0 flag tells find to use \0 (null character) delimiters between filenames, and the -0 flag tells xargs to expect these \0 delimiters.

Laurence Gonsalves
+4  A: 

1) Piping to another process (Although this WON'T accomplish what you said you are trying to do):

command1 | command2

This will send the output of command1 as the input of command2

2) Exec on a find (This will do what you are wanting to do -- but is specific to find)

find -name '*.foo' -exec cat {} \;

(everything between find and -exec are the find predicates you were already using. {} will substitute the particular file you found into the command (cat {} in this case) the \; is to end the exec command

3) send output of one process as command line arguments to another process

command2 `command1`

for example:

cat `find -name '*.foo' -print`

(Note these are BACK-QUOTES not regular quotes (under the tilde ~ on my keyboard)) this will send the output of command1 into command2 as command line arguments.

kenj0418
cat `find -name '*.foo' -print` worked great for me ... Thanks
Devang Kamdar
A: 

To list and see contents of all abc.def files on a server in the directories /ghi and /jkl

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;

To list the abc.def files which have commented entries and display see those entries in the directories /ghi and /jkl

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
Sharjeel Sayed