On Sat, Aug 30, 2025 at 15:07:10 +0200, pourko--- via Bug reports for the GNU
Bourne Again SHell wrote:
> After upgrading to bash-5.3, I ran into a strange problem with many of my
> scripts: It looks like in bash-5.3, setting the extglob option can crash my
> script, if the shopt command is inside an if-then-fi structure, or if it's
> inside a for-do-done loop. For example, here is a snippet that works fine in
> bash-5.2, but breaks in bash-5.3:

> #---------------------------------------
> shopt -u extglob
> # [...]
> if true; then
>   shopt -s extglob
>   echo /!(tmp.txt)
> fi
> #---------------------------------------
> ...and it bombs really bad, it aborts the whole script.

I get the same behavior in 5.2 and 5.3:

hobbit:~$ cat x
shopt -u extglob
if true; then
  shopt -s extglob
  echo /!(tmp.txt)
fi
echo still here
hobbit:~$ bash-5.2 x
x: line 4: syntax error near unexpected token `('
x: line 4: `  echo /!(tmp.txt)'
hobbit:~$ bash-5.3 x
x: line 4: syntax error near unexpected token `('
x: line 4: `  echo /!(tmp.txt)'

This is the expected behavior.  Turning on extglob changes how bash
parses its input, and bash has to parse compound commands (if, for,
while and so on) as a whole.

So, regardless of version, bash reads the first line, "shopt -u extglob",
parses it as a simple command with two arguments, and executes it.  At
this point, the extglob feature is disabled.

Next, bash reads the "if true; then" line and parses it as the start of
a compound command.  It continues reading lines until it has the entire
compound command:

    if true; then
      shopt -s extglob
      echo /!(tmp.txt)
    fi

At that point, it can begin to parse it.  Note that the extglob feature
is still turned off at this point.  When it tries to parse the "echo"
line, it encounters a syntax error, reports it, and aborts.

If you want to turn on extglob, you must do it *before* parsing any
commands that use the feature.  This means you can't do "shopt -s extglob"
inside a function, a for loop, an if/then, a case statement, etc.  All
of these are compound commands, and must be parsed as a whole before
executing any of the simple commands contained inside them.

I always advise people that if they're going to use extglob, it should
be done right up at the top of the script, either immediately below
the shebang, or after any mandatory comments that their boss demands
be present.  Definitely before any function declarations or loops.

Reply via email to