10

I need to search the first 50 lines of every file in a directory and its subdirectories.

This will do the recursive part, but how do I limit to just the first 50 lines of each file?

grep -r "matching string here" .

Some of these files are huge, and I only want them to match in the first 50 lines. I'm trying to speed up the process by not searching megabytes of binary data in some files.

1
  • do you want to just know the files that match, or do you want to have just the matching string or do you want the matching string together with the filename? Oct 29, 2013 at 19:13

3 Answers 3

11
  • If you just want the files that match:

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1")' _ {} \; -printf '%p\n'
    

    or

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1") && printf '%s\n' "$1"' _ {} \;
    
  • If you only want the matching strings:

    find . -type f -exec head -n 50 {} \; | grep "matching string here"
    

    or, better,

    find . -type f -exec head -q -n 50 {} + | grep "matching string here"
    
  • And if you want both:

    find . -type f -exec bash -c 'mapfile -t a < <(head -n 50 "$1" | grep "matching string here"); printf "$1: %s\n" "${a[@]}"' _ {} \;
    

Remarks.

  • Could be slightly easier with sed instead of the combo head--grep.
  • Let me stress that all three methods are 100% safe regarding file names that may contain funny symbols (spaces, newlines, etc.).
  • In two of these methods, I'm assuming you have a decently recent version of bash.
  • You could use -exec ... + in each method, but then you'll have to code your inner loop yourself! (trivial exercise left to the reader). This might be very slightly more efficient if you have a gazillion files.
4

If you need the grep output as in the original, you could do:

find . -type f | while read f; do 
  if head -n 50 "$f"|grep -s "matching string here"; then
    grep "matching string here" "$f" /dev/null 
  fi
done

If you only need the file names you can replace the 2nd grep with echo "$f".

1

You'll need to combine a few different utilities to get the desired functionality. Use the find command to recurse the directories, find all files and execute the head command on each file found. The head command can be used to dump only the first 50 lines of each file. Finally, pipe the output to grep to search for your desired string.

find . -type f -exec head -n 50 {} ";" | grep "matching string here"

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .