1

I want to count the number of matches in a directory.

grep -rn 'hello' . works properly, printing line numbers and recursively going through the current directory.

grep -rc 'hello' ., on the other hand, seems to print out every file in current directory without returning a count.

There's a similar question and answer that shows a way to do it by piping the results of grep -r <pattern> <directory> to wc -l, but I am wondering why my command above doesn't work and if there is a way to do it using just grep options.

1
  • That is how the -c option should work: it lists every input file and append the numer of matches (or 0) right after the file name. Check grep manpage for more details. I honestly don't know if there's some kind of 'grand total' option available. Jan 10, 2017 at 20:23

1 Answer 1

2

This is expected.

grep -r -n will perform a recursive grep, displaying the lines which matches the given pattern, prefixed with the name of the file and the line number. It will give you every line that has a match in each file.

-n Each output line is preceded by its relative line number in the file, starting at line 1. The line number counter is reset for each file processed.

grep -r -c will perform a recursive grep, displaying the filenames of all files considered, followed by the number of matches of the pattern in that file. It will give you one line for each file.

-c Only a count of selected lines is written to standard output.

To get the number of matches of a pattern in any file in a particular directory (recursively), you may feed the result of grep -r to wc -l as suggested in the answer that you link to:

$ grep -r 'pattern' . | wc -l

To only use grep to achieve this:

$ grep -r 'pattern' . | grep -c 'pattern'

Although it is certainly overkill to employ a regular expression engine for this job when using wc to count newlines is "the right tool for the job".

Note that there is also the -o flag to grep:

-o Print each match, but only the match, not the entire line.

This may be useful if you want to count each individual match on each line separately:

$ grep -r -o 'pattern' . | wc -l

Compare, for example, the following two grep invocations (in bash or ksh93):

$ grep 'l' <<<"Hello world!" | wc -l
1

$ grep -o 'l' <<<"Hello world!" | wc -l
3
3
  • I suppose what is primarily confusing part is that -c options documents says "Only a count of selected lines is written to standard output" but doesn't say whether it's going to be a total number, whether it's only going to look at those files that matched, or whether it's going to look at all files and give a count for each file.
    – Govind Rai
    Jan 30, 2017 at 21:17
  • And furthermore what doesn't make logical sense is why grep would stdout "all files considered" anyways--I mean grep is supposed to look for matches--why bother giving useless output? Seems a bit broken to me...
    – Govind Rai
    Jan 30, 2017 at 21:20
  • @GovindRai -c will make grep report the count of the matching lines. This count may be zero. It looks at all files, but as with all operations on multiple file, reports the result individually for each file. If you wanted to, you could just cat all files to grep and let it handle it as one single input stream.
    – Kusalananda
    Jan 30, 2017 at 21:41

You must log in to answer this question.

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