10

What is the difference between:
grep "string" . -r --include *.pl

and

grep "string" . -r --include "*.pl"

The latter includes files in subdirectoried while the former not. Why?

1
  • The difference isn't in grep; it's in the shell. grep never sees the quotes.
    – Wildcard
    Jan 11, 2017 at 0:08

2 Answers 2

18

The * (star, or asterisk) is a special character which is (usually) interpreted by the shell before it is given the command. It is (usually) expanded to all filenames except those with leading dots. See the bash manual about pattern matching for more information.

If placed in quotes the star will not be interpreted by the shell and is given to the command verbatim.


Examples explained. The quoted one:

grep "string" . -r --include "*.pl"

Here grep will receive the option --include with the argument *.pl. That is a 4 character string starting with the character *. What grep does with that string is entirely up to grep. In this case --include means to only consider files matching the glob *.pl.

AFAIK behind the scenes gnu grep uses the same pattern matching lib as gnu bash. That means it will include the same files as shown by echo *.pl.

The not quoted one:

grep "string" . -r --include *.pl

Here the shell will first expand the glob *.pl before executing the command. The glob will expand to all filenames ending in .pl.

Suppose there are the files foo.pl, bar.pl and baz.pl. After expanding the glob the command line looks like this:

grep "string" . -r --include foo.pl bar.pl baz.pl

Here grep will receive the option --include with the argument foo.pl, followed by the options bar.pl and baz.pl.

--include foo.pl instructs grep to only consider files matching the pattern foo.pl. Since there are no wildcards (no stars) in the pattern the only file matching that will be the file named foo.pl.

The options bar.pl and baz.pl instructs grep to also search in those files. But since they do not match the pattern foo.pl they will be ignored as required by the previous --include.

1
  • This is a great observation. I always wondered why grep -r seemed inconsistent but never noticed it was only when I used a *.
    – j883376
    Jul 8, 2013 at 8:38
6

The difference is that if you don't quote the pattern (*.pl) it is expanded by the shell. For example, if you run your grep in a directory that contains a file called foo.pl, since the *pl is expanded by the shell, what grep actually sees is:

grep "string" . -r --include foo.pl

Since you tell it to only include foo.pl it will only search through that one file.

If you quote your pattern, the shell will not expand it and grep gets the correct command, namely

 grep "string" . -r --include *pl
2
  • peopl will not get expanded by *.pl.
    – unxnut
    Jul 7, 2013 at 21:35
  • @unxnut good point, answer edited.
    – terdon
    Jul 7, 2013 at 21:59

You must log in to answer this question.

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