Restricting our focus exclusively to bash, in this answer on Stack Overflow it is reported the following.
extglobis a flag used by the parser. Functions, compound commands, &c. are parsed in entirety ahead of execution. Thus,extglobmust 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 (whenextglobis 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.
ls !(*.txt)withoutextglobgets refused when the command is split into token, being abashsyntax error and therefore it is reasonable to guess thatextglobhas to be enabled before the content is parsed. Forecho *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.extglobcan 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.!(foo)is accepted by the parser withextglobdisabled. 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.