2

I have many files I need to search for some string. I'm using grep -rl 'pattern' * to find files that contain the pattern. However, I'm only interested in file count - if string occurs in more than N files, I want grep to stop immediately after hitting Nth match(as searching through the whole file hierarchy is long operation). It would be nice if it returned some meaningful exit code, but if that's impossible then I can just pipe it to wc without a problem.

How can I tell grep to stop searching other files after matching Nth file?

7

You can pipe grep result to head.

Note, that in order to ensure stopping after Nth match, you need to using stdbuf to make sure grep don't buffer its output:

stdbuf -oL grep -rl 'pattern' * | head -n10

As soon as head consumed 10 lines, it terminated and grep will receive SIGPIPE because it still output something to pipe while head was gone.

This assumed that no file names contain newline.

  • Will that do what OP expects if there are N (e.g. 10) matches in the first file? Just curious if OP is wanting N files as opposed to the first N matches ? – Jeff Schaller Aug 24 '15 at 14:12
  • @JeffSchaller -l flag makes grep stop searching file after first match. Yes, I want first N matched files. However, I'm trying out head now and it looks like it doesn't stop execution when encountering Nth result. However, it may only be coincidence, as this grep is generally lengthy. Going to check and see if it really works for me. – MatthewRock Aug 24 '15 at 14:14
  • Ah - missed the -l flag; it does the right thing for me -- sigchld after N lines of output from grep. – Jeff Schaller Aug 24 '15 at 14:20
  • @JeffSchaller: Ah, well, a little confusing between the title and the question from OP. -l option work well in this case, stop scanning file after first match. – cuonglm Aug 24 '15 at 14:30
  • 3
    You'd want to run grep with stdbuf -oL (if on GNU or FreeBSD) so that it doesn't buffer its output. Otherwise, it's only going to be killed after it writes 2 full buffers, 8k on GNU/Linux which is a very large file list. – Stéphane Chazelas Aug 24 '15 at 14:43
0

Not pure grep, but with bash:

i=0
grep -rl 'pattern' * | while read l ; do
  i=$(($i+1))
  echo $l
  if [ $i -ge N ] ; then 
    echo "at least N matches"
    break
  fi
done

Will be faster if you have far more files matching than your threshold of N matches.

  • oh - copy and paste error - corrected. – Fiximan Aug 24 '15 at 13:32
  • For each line there was an error(or so it seems), but that means that script still waited for all lines before processing lines, so no interruption of command I wanted to achieve. – MatthewRock Aug 26 '15 at 12:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.