Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Why I can't grep find? Only helps grepping cat of find. As I see program grep could see some context in which every command runs. But it's counterintuitive for a newbie like me. When given with argument grep can search files , but when it's with pipe ( | ) - it couldn't.

share|improve this question
1  
unix.stackexchange.com/questions/9125/… solution to same problem.. –  week Nov 17 '12 at 15:12
    
Both work, one looks for dashes the other for RESTRICT, what makes you conclude it doesn't work? –  Ярослав Рахматуллин Nov 18 '12 at 0:15
add comment

2 Answers

The find command generates a list of pathnames that match the search criteria, in this case, a name with an .ebuild extension. (But minor quibble: You need quotes around the wildcard so the shell will pass it to find without trying to expand it first.) If you pipe that into grep, all you're doing is filtering that list of names, not the contents of those files.

By contrast, the cat $(find ...) construct uses command substitution (that's the $(...) part) to paste the output of find (the list of pathnames it generates) back onto the command line as arguments to cat, causing cat to write the contents of those files to stdout and into grep.

The simpler way to do what you want would be to use command substitution to pass the names to grep directly:

grep RESTRICT $(find /usr/portage -name "e.build")
share|improve this answer
    
That is exactly what I was thinking. I might add a -maxdepth argument in there as well depending on the end goal. –  nerdwaller Nov 17 '12 at 15:13
add comment

To express Nicole Hamilton's command in a more concise form you can use the -exec flag to the find command.

find /usr/portage -name '*.ebuild' -exec grep RESTRICT {} \;

This passes the names of the matched files to grep with the curly brackets being replaced by the filename. The '\;' is an escaped ';' this is used to signify the end of the command.

Performance @garyjohn

This is a comparison of different timings for running the find command. All these tests where performed against a recent snapshot of portage (http://distfiles.gentoo.org/snapshots/portage-latest.tar.bz2). I ran 'find .' and 'grep -Rni . .' before timeing these tests so I'm hoping that disk and ram caching should be simular across all tests.

Here is the timing for the two commands:

% time grep RESTRICT $(find . -name "*.ebuild") > /dev/null
grep --color RESTRICT $(find . -name "*.ebuild") > /dev/null  0.05s user 0.13s system 95% cpu 0.192 total

% time find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null
find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null  0.68s user 2.63s system 14% cpu 22.523 total

As your can see the cat method is much quicker completing in about 5% of the time of my example.

However if the find command returns too many files we run into a limit of the shell with the lenght of a single command. This will cause the command to fail.

% time grep RESTRICT $(find . -name "*") > /dev/null
zsh: argument list too long: grep
grep --color RESTRICT $(find . -name "*") > /dev/null  0.34s user 0.04s system 99% cpu 0.374 tota

To see this limit on your system use.

getconf ARG_MAX

Here is find running with the same glob. Notice that it takes a very long time to complete but it does exit succesfully.

% time find . -name "*" -exec grep RESTRICT {} \; > /dev/null    
find . -name "*" -exec grep RESTRICT {} \; > /dev/null  2.52s user 11.00s system 12% cpu 1:47.67 total

The optimal way to safley run this command is to use xargs.

% time find . -name "*" -print0 | xargs -0 grep RESTRICT > /dev/null 
find . -name "*" -print0  0.16s user 0.29s system 51% cpu 0.886 total
xargs -0 grep RESTRICT > /dev/null  0.33s user 0.59s system 100% cpu 0.915 total

Using xargs it is possible to grep through the entire portage tree (~159995 files, 724M) in just under 2 seconds.

share|improve this answer
1  
This is slower--possibly much slower--than Nicole's command because it executes grep once for every file searched. –  garyjohn Nov 17 '12 at 18:18
    
Thanks for the timing comparison. Good point about using xargs if the arg list is too long. In this case that appears not to be a problem given that the OP states that command substitution onto cat worked. –  Nicole Hamilton Nov 17 '12 at 22:47
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.