1

In several manuals (including the official GNU/Linux Command-Line Tools tldp.org) is recommended to use single (or double quotes) to avoid bash to interpret wildcards or regex symbols like caret (^) and dollar ($).

But in some examples that's not necessary to use single/double quotes. For instance:

(1)

$ touch 'fo*'

and

$ touch fo*

creates the same file fo* in both command line forms.

(2)

$ grep '^foo' file.txt

and

$ grep ^foo file.txt

both search for foo as a string in beginning of the lines of file.txt.

Why manuals recommend to use single/double quotes to avoid bash interpretation if bash in fact does not interpret some wildcards and regex symbols in first place?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Caco
  • 1,601
  • 1
  • 26
  • 53
  • 1
    ... Because Murphy's Law is a thing. – Ignacio Vazquez-Abrams Jul 01 '16 at 19:31
  • 3
    Possible duplicate of [How do I escape the wildcard/asterisk character in bash?](http://stackoverflow.com/questions/102049/how-do-i-escape-the-wildcard-asterisk-character-in-bash) – TemporalWolf Jul 01 '16 at 19:34
  • 1
    The 2nd highest answer above has a good synopsis of why. – TemporalWolf Jul 01 '16 at 19:34
  • It interprets them **when something matches**. So if you have a `foobar`, then `touch fo*` will expand to that. It's even more fun (read: unpredictable and convoluted) if you have non-default shell options set. – Charles Duffy Jul 01 '16 at 19:36
  • http://stackoverflow.com/a/104023/14122 is definitely a great answer; unfortunately, while the answer is on-point, I'm not certain that that's also true for the question itself. – Charles Duffy Jul 01 '16 at 19:40
  • BTW, glob patterns are not regular expressions; the regex tag is completely off-topic here. – Charles Duffy Jul 01 '16 at 19:41
  • 2
    Quoting `^foo` is not strictly necesssary; `^` is special in regular expressions, but not in glob patterns. Still, it's easier to quote it than to prove to yourself that you don't need to (as I write this I'm not even 100% certain myself). – Keith Thompson Jul 01 '16 at 19:52
  • @KeithThompson, quite -- there's enough potential for some shell to implement a new `extglob` (or history-expansion) option that even if you don't need to quote `^` today, you might need to quote it tomorrow. – Charles Duffy Jul 01 '16 at 20:11

2 Answers2

6

If there is a file named foo in the current directory, then touch 'fo*' touches fo*, but touch fo* would expand to touch foo and touch that instead.

If the nullglob option is set and no file name matching fo* exists, touch fo* would expand to just touch and complain about the missing operand.

If the failglob option is set and no file name matching fo* exists, touch fo* would immediately cause an error.

  • 1
    `failglob` is an important option that is often overlooked in these types of questions. I didn't fully appreciate this until I started using `zsh`, where the `failglob` behavior is the default, and I needed to start quoting URLs with `?` in them when running `curl`. – chepner Jul 01 '16 at 20:10
1

Bash indeed does expand all wildcards, as seen with the right preconditions.

nullglob:

shopt -q nullglob && ! compgen -G 'f*' >/dev/null && touch f*
touch: missing file operand

nullglob

If set, Bash allows filename patterns which match no files to expand to a null string, rather than themselves.

failglob:

shopt -q failglob && ! compgen -G 'f*' >/dev/null && touch f*
bash: no match: f*

failglob

If set, patterns which fail to match filenames during filename expansion result in an expansion error.

srage
  • 990
  • 1
  • 9
  • 27
  • 1
    ...I might also have the example create, and `cd` into, an empty directory, just to be sure that `f*` doesn't expand to something. That, or use a longer and thus less-likely-to-collide name (ie `foo-nonexistent*`). – Charles Duffy Jul 01 '16 at 19:45
  • @CharlesDuffy good idea. I went with the answer to http://stackoverflow.com/questions/2937407/test-whether-a-glob-has-any-matches-in-bash as a necessary precondtion. – srage Jul 01 '16 at 20:07