Victor
Victor

Reputation: 243

Shell UNIX : grep wild card

I can't figure out why the wild character * is interpreted differently in the following examples with grep :

find . -type f -name \*

Results :

./tgt/etc/test_file.c
./tgt/etc/speleo/test_file.c
./tgt/etc/other_file.c
./src/file.c

I want to return from this command the files that match a pattern with eventually a wildcard *. But :

find . -type f -name \* | grep "tgt/etc/*" # this one works
find . -type f -name \* | grep tgt/etc/* # not this one
find . -type f -name \* | grep tgt/et*/s* # this one works
find . -type f -name \* | grep "tgt/et*/s*" # not this one

I'd like to have an implementation which works fine with both cases. What should I use ?

Upvotes: 3

Views: 11216

Answers (3)

Barmar
Barmar

Reputation: 780688

The first argument to grep is not a wildcard, it's a regular expression. In a regular expression, * means to match any number of the character or expression that precedes it. So

grep "tgt/etc/*"

means to match tgt/etc followed by zero or more / characters. In a wildcard, * means to match any number of any characters, the equivalent regular expression is .*. For your purposes, the commands you want are:

find . -type f -name \* | grep "tgt/etc/"
find . -type f -name \* | grep "tgt/et.*/s"

Also, if you don't quote the argument, and it contains any * characters, the shell will expand the argument as a filename wildcard before passing them as arguments to grep. So when you write:

find . -type f -name \* | grep tgt/etc/*

the shell will expand this to

find . -type f -name \* | grep tgt/etc/file1 tgt/etc/file2 tgt/etc/file3

This will treat the tgt/etc/file1 as the regular expression to search for, and look for it inside the remaining files -- it will not process the input from the pipeline because it was given filename arguments.

Upvotes: 5

zmo
zmo

Reputation: 24812

it's because grep uses regexps and no wildcards.

so basically, what you do is:

  • tgt/etc/* checking zero or sereval /
  • tgt/et*/s* checking zero or several t and zero or several s

but thing is that when you do not put quotes around the regexp, the shell is expanding the * as wildcards, which messes up the regexp grep sees.

Upvotes: 1

Christopher Creutzig
Christopher Creutzig

Reputation: 8774

The unquoted examples (without the ") are expanded by the shell, before grep ever sees them. That is just the way Unix shells work.

For the quoted ones, note that * in a grep pattern means something different from what it means to the shell and to find: It means “repeat the preceding character any number of times (including zero).”

Upvotes: 3

Related Questions