0

This works in shell:

grep -R --exclude-dir=storage --exclude-dir=node-modules --include=*.{scss,css} loader.gif

But this fails:

sh -c "grep -R --exclude-dir=storage --exclude-dir=node-modules --include=*.{scss,css} loader.gif"

It fails without any message, it just can't find any occurrence.

This works:

sh -c "grep -R --exclude-dir=storage --exclude-dir=node-modules --include=*.scss loader.gif"

Why the use of curly braces in --include=*.{scss,css} fails?

pamoka
  • 1
  • 4
    because `sh` has no brace-expansion, use for example `bash` or `zsh` or `csh`. see also [Why is brace expansion not supported?](https://unix.stackexchange.com/questions/92819/why-is-brace-expansion-not-supported) – αғsнιη Feb 11 '20 at 17:48
  • In a shell that supports brace-expansion you can supply: `--include=*.{s,}css` – Paulo Tomé Feb 11 '20 at 17:50
  • 1
    Don't use all those wacky GNU grep options for finding files. Keep your scripts simple and use `find` to **find** files and `grep` to **g/re/p** within files. There are clues in the tools names to their intended use! – Ed Morton Feb 17 '20 at 20:43

2 Answers2

2

Probably because your sh is plain POSIX sh (or at least plainer than your login shell), and doesn't support brace expansion. Of Linux systems, this is the case by default in at least Debian and Ubuntu. If you want to run Bash, run bash -c instead.

ilkkachu
  • 133,243
  • 15
  • 236
  • 397
2

Because of "time of expansion".

Lets simplify the command:

$ echo --include=*.{scss,css}
--include=*.scss --include=*.css

As you can see, the braces were expanded by the "present running shell" (probably bash). And the * was not expanded as probably there is no file which name start with --include= and also ends on .scss (or .css) in the present directory.

However, in:

$ sh -c "echo --include=*.{scss,css}"
--include=*.{scss,css}

Two things happen:

  • the present running shell (PRS) doesn't expand the braces because they are quoted and are given literally to the next shell sh -c.

  • the next shell doesn't support brace expansion as leaves them as they are. Printing them with echo.

So, either make the PRS expand the braces:

sh -c 'echo "$@"' mysh --include=\*.{scss,css}

Which is complex and not the recommended solution. Or, use a brace aware shell:

bash -c 'echo --include=\*.{scss,css}'

Both * are quoted to prevent their expansion.