16

Maybe it's a bit strange - and maybe there are other tools to do this but, well..

I am using the following classic bash command to find all files which contain some string:

find . -type f | xargs grep "something"

I have a great number of files, on multiple depths. first occurrence of "something" is enough for me, but find continues searching, and takes a long time to complete the rest of the files. What I would like to do is something like a "feedback" from grep back to find so that find could stop searching for more files. Is such a thing possible?

migrated from stackoverflow.com Dec 9 '11 at 15:51

This question came from our site for professional and enthusiast programmers.

20

Simply keep it within the realm of find:

find . -type f -exec grep "something" {} \; -quit

This is how it works:

The -exec will work when the -type f will be true. And because grep returns 0 (success/true) when the -exec grep "something" has a match, the -quit will be triggered.

8
find -type f | xargs grep e | head -1

does exactly that: when the head terminates, the middle element of the pipe is notified with a 'broken pipe' signal, terminates in turn, and notifies the find. You should see a notice such as

xargs: grep: terminated by signal 13

which confirms this.

  • +1 for explanation and the alternative, though the other answer seems more elegant to me, since it is more self-sufficient – hello_earth Jan 16 '13 at 9:21
7

To do this without changing tools: (I love xargs)

#!/bin/bash
find . -type f |
    # xargs -n20 -P20: use 10 parallel processes to grep files in batches of 20
    # grep -m1: show just on match per file
    # grep --line-buffered: multiple matches from independent grep processes
    #      will not be interleaved
    xargs -P10 -n20 grep -m1 --line-buffered "$1" 2> >(
        # Error output (stderr) is redirected to this command.
        # We ignore this particular error, and send any others back to stderr.
        grep -v '^xargs: .*: terminated by signal 13$' >&2
    ) |
    # Little known fact: all `head` does is send signal 13 after n lines.
    head -n 1
  • 1
    +1 never knew xargs would have such multitasking capabilities - thanks for other comments as well! :) – hello_earth Feb 5 '14 at 10:53

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.