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

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
  • 138,973
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.