Return only one line per file with grep in Terminal

command lineterminal

Various posts in other forums have suggested that the best way to use grep to return a single line per file is using -m 1, which is the --max-count option. However, when I write the following line, I get only one file, not one line per file:

grep -m 1 "library" ./ -R

Returns a single file on a single line:

.//results/fig/fig_functions.R:# library(plyr)

Whereas

grep "library" ./ -R

Returns many files, each with multiple lines:

.//results/fig/fig_functions.R:# library(plyr)
.//results/fig/fig_functions.R:# library(grid)
.//src/rmd/genevese_params.html:library(sf) 
.//src/rmd/genevese_params.html:library(raster)
[many more lines and files...]

I would like the command to return all files containing the text, but only return one line per file. Am I using grep incorrectly or is there another way to do this?

Best Answer

It's not working as expected because Macs use a BSD version of grep while the answers you're seeing are for GNU grep as found on Linux. They're very similar but not identical, and they handle -m differently. BSD grep treats -m as covering the full output, while GNU's version is per-file.

One way to get the result you describe is like this:

find . -type f -exec grep -H -m1 library '{}' \;

This uses find to get the path to every file in . (recursively, so it gets all sub-directories) an then runs grep -m1 on each of them. The -type f tells find to only get regular files, not directories and other things. The -H tells grep to print the names of matching files, not just the matching text.

Another way would be to install GNU grep, using Homebrew.