Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

grep --include command doesn't work in OSX Zsh

Tags:

grep

macos

zsh

I am following the best answer on How do I find all files containing specific text on Linux? to search string in my project.

This is my command grep --include=*.rb -rnw . -e "pattern"

Zsh tells me that zsh: no matches found: --include=*.rb

It seems that grep doesn't support --include option.

When I type grep --help, it returns

usage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
    [-e pattern] [-f file] [--binary-files=value] [--color=when]
    [--context[=num]] [--directories=action] [--label] [--line-buffered]
    [--null] [pattern] [file ...]

no --include here.

Is my grep version too old? Or is there something wrong with my command?

like image 815
icemelon Avatar asked Jun 13 '14 03:06

icemelon


People also ask

Does grep work in Mac terminal?

To locate a string within a file, use the grep tool. The grep tool searches the named input files for lines containing a match to the given pattern. By default, grep prints the matching lines.

What is grep in shell script?

In Linux and Unix Systems Grep, short for “global regular expression print”, is a command used in searching and matching text files contained in the regular expressions.


2 Answers

FreeBSD/macOS grep does support the --include option (see man grep; it's unfortunate that the command-line help (grep -h) doesn't list this option), but your problem is that the option argument, *.rb, is unquoted.

As a result, it is your shell, zsh, that attempts to pathname-expand --include=*.rb up front, and fails, because the current directory contains no files with names matching glob pattern *.rb.
grep never even gets to execute.

Since your intent is to pass *.rb unmodified to grep, you must quote it:

grep --include='*.rb' -rnw . -e "pattern"     

To include multiple globs:

  • Pass an --include option for each; e.g.:

    grep --include='*.rb' --include=='*.h*' -rnw . -e "pattern"     
    
  • Alternatively, in shells that support brace expansion - notably bash, ksh, and zsh - you can let your shell create these multiple options for you, as follows - note the selective quoting (see this answer for a detailed explanation):

    grep '--include=*.'{rb,'h*'} -rnw . -e "pattern"     
    
like image 93
mklement0 Avatar answered Oct 17 '22 01:10

mklement0


If your grep does not support --include, and you don't want to install GNU grep just for this, there are a number of portable ways to perform the same operation. Off the top of my head, try

find . -type f -name '*.rb' -exec grep -nw "pattern" /dev/null {} \;

The find command traverses the directory (like grep -r) looking for files named *.rb (like the --include option) and the /dev/null is useful because grep shows a slightly different output format when you run it on multiple files.

This is slightly inefficient because it runs a separate grep for each file. If it's too slow, look into xargs (or use find -exec ... {} \+ instead of ... {} \; if your find supports that). This is a very common task; you should easily find thousands of examples.

You might also want to consider ack which is a popular and somewhat more user-friendly alternative. It is self-contained, so "installation" amounts to copying it to your $HOME/bin.

like image 3
tripleee Avatar answered Oct 17 '22 02:10

tripleee