1

Restricting our focus exclusively to bash, in this answer on Stack Overflow it is reported the following.

extglob is a flag used by the parser. Functions, compound commands, &c. are parsed in entirety ahead of execution. Thus, extglob must be set before that content is parsed; setting it at execution time but after parse time does not have any effect for previously-parsed content.

This is also why you can't run shopt -s extglob; ls !(*.txt) as a one-liner (when extglob is previously unset), but must have a newline between the two commands.

However, this is not true for other shell options. Consider e.g. the following.

$ ls -a
.  ..  .hiddenFile  file1  file2  file3
$ shopt dotglob
dotglob         off
$ echo *
file1 file2 file3
$ shopt -s dotglob; echo *
.hiddenFile file1 file2 file3

Is it documented somewhere which shell options are used by the parser like extglob and therefore cannot be enabled within a group command that uses them?

In the shopt page in the bash manual nothing about the behaviour above seems to be mentioned.

3
  • You have a good point. ls !(*.txt) without extglob gets refused when the command is split into token, being a bash syntax error and therefore it is reasonable to guess that extglob has to be enabled before the content is parsed. For echo * this is not the case, because the parser knows how to interpret it. I wonder if the logic is always so trivial, though. Is it then the following a valid conclusion? If the code runs fine without the shell option enabled, then such an option is not used by the parser. – Axel Krypton Mar 18 '20 at 14:31
  • @AxelKrypton, extglob can change the meaning of a command line, it might not be the case that the alternative is always a syntax error. e.g. !(foo) is valid with and without extglob. If it "runs fine" depends on intent. – ilkkachu Mar 18 '20 at 14:45
  • @ilkkachu Indeed, !(foo) is accepted by the parser with extglob disabled. I would then come back to my original question and be convinced that it would be interesting to know which shell option can and which cannot be enabled within a group command that uses it. – Axel Krypton Mar 18 '20 at 14:51
1

Is it documented somewhere which shell options are used by the parser like extglob and therefore cannot be enabled within a group command that uses them?

It's hard to prove a negative, but I doubt there's a comprehensive list.

The ones I found that affect parsing are below, there may be others:

  • extglob -- changes the meaning of the parenthesis, which are otherwise a special character
  • expand_aliases -- aliases get expanded rather early in the processing
  • extquote -- changes the meaning meaning of some quotes
  • interactive_comments -- changes the meaning of # at the start of word.

Some of the compat* options might also have similar effects, but I'll leave testing them to someone more interested.

On the other hand, something like dotglob, failglob and globstar only affect the result of a glob, not how it's parsed.

Regarding extglob, a command line like !(foo) is valid either with extglob set, or without it. With it, it's a glob that matches all files but foo, and without it, it's a subshell running the command foo, with the return value inverted.


Note that in practice, this shouldn't be a problem. In a script, you can put the shopt command on a line of its own, so the changing in parsing affect the next line without problems. In a one-liner, you can use the -O option on the command line, e.g. in bash -O extglob -c 'echo !(foo)', the extended glob works.

4
  • Your answer is a starting point. * you can put the shopt command on a line of its own, so the changing in parsing affect the next line without problems* - well, as I wrote in the question, this is not true inside a group command that uses it. And this is the relevant point in (complex) scripts. About !(foo), it is different from ! (foo) and your description applies to the second, I would say. Without a space, it should be seen as a history expansion, isn't it? – Axel Krypton Mar 18 '20 at 15:27
  • @AxelKrypton, can you clarify what you mean with a group command? – ilkkachu Mar 18 '20 at 15:52
  • I took the expression from Greg's Wiki in the extglob section (search for group command in the page). Since there is this link on group command, I think the correct name is compound command. So, most keywords, sub shells, command grouping {...}, etc. Indeed, writing shopt -s extglob in an if clause and e.g. echo +(*.txt) in the same clause fails. – Axel Krypton Mar 18 '20 at 16:09
  • @AxelKrypton, ah yes, you're right. The shell reads and parses the whole compound command before executing any of it, and it does the same for lines, even though they're not compound commands in the same way. Hmm. – ilkkachu Mar 18 '20 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.