I need to recursively find all files that contain a specific word and if the word exists in file I need to find out the number of lines in that file. I have been trying to use grep but I have been not successful so far.

  • 3
    Welcome to U & L SE. Show us the sample input and the output that you are expecting. Also show the grep command that you tried. If you provide these information, it will assist you in getting an answer quickly :)
    – Ramesh
    May 23, 2014 at 3:47

1 Answer 1

grep -Zlr "\<THE_WORD\>" * | xargs -0 wc -l

Options for grep:

  • -Z - end printed filenames with a zero/null byte to delimit them (helps with weird filenames, or those with spaces)
  • -l - list names of files, not the lines that match
  • -r - recursively
  • -i - ignore case (optional, but probably useful to find ALL the variants)

And in the quotes, around THE_WORD, I've used 'word delimiters' (\< and \>), which prevent 'HI' from being found in 'WHICH'. Useful, that.

Pipe the zero delimited list of filenames containing "THE_WORD" to xargs, telling it to expect zero byte delimiters (-0), execute wc (word-count), showing line counts (-l)


To answer your query in the comments, try this variation: (I've done some research!)

grep -oi "\<THE_WORD\>" /dev/null * | sort | uniq -c 

And explanation:

  • -o says to output EVERY occurrence on the line, so if you have "blah blah THE_WORD blah THE_WORD blah blah", it'll output TWICE for that LINE, without this flag, grep would only output ONCE for this line.
  • -i match upper & lowercase variations (ie, The_Word, the_word, etc)
  • \< must be a start of a word, thus 'HI' is NOT found in 'WHICH'.
  • `>' must end on end of a word, again preventing 'HI' being found in 'WHICH'
  • /dev/null a dummy filename to force grep to ALWAYS output filenames, even if you only search one file. This CAN be forced by using the -H option for grep, but I find this just as easy and more descriptive since -H could be rated as 'little-known-magic'

  • pipe all that to sort (which, uh.... sorts...)

  • pipe the sorted list to uniq, with -c to count each occurrence in the sorted list

And taadaa!!

An example:

File example.c contains:


xenon-lornix:~/projects/emma> grep -oi "\<H\>" /dev/null *.c | sort | uniq -c
  3 example.c:H

Thus returning a list of a count (3), where (example.c), and what (H)!! Voila!! Yaaayy!!

Another, with same file contents:

xenon-lornix:~/projects/emma> grep -oi "\<segments\>" /dev/null example.c | sort | uniq -c
  2 aa.c:segments

You can see here it found both segments, but didn't count segment. The \< & \> force matching only entire words. THE_WORD123 does NOT match _THE_WORD_, word breaks are at non-alpha-numeric characters. FYI.

  • 1
    grep implementations that support \< generally also support -w. Only GNU grep and OpenBSD grep support -Z though and OpenBSD grep supports -w but not \< (it uses [[:<:]]). GNU and OpenBSD xargs need a -r to avoid running the command if there's no argument. (otherwise, wc would count the lines on stdin). You probably want . instead of * unless you want to exclude the hidden files in the current directory only. Also beware of filenames that start with -. May 23, 2014 at 13:07
  • Thanks this is what I was looking for. I am doing some analysis on repositories and based on this command I am able to get results of all repositories. However I need to group the results based on each repository. Is there a command that I can use ? If not I plan to java code.
    – user68336
    May 29, 2014 at 4:20

You must log in to answer this question.

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