Re: Parameter assignment in a redirection word
Bart Schaefer <[email protected]> Sun, 26 Oct 2025 11:16:07 -0700
| Newsgroups | gmane.comp.shells.zsh.devel,gmane.comp.shells.zsh.user |
|---|---|
| Message-ID | <CAH+w=7bHhDqm98hnychSDHjiNgvsM-m6iC8tnQ43z0HLYWxsHg@mail.gmail.com> |
On Sun, Oct 26, 2025 at 10:18 AM Mark J. Reed <[email protected]> wrote: > > On Sun, Oct 26, 2025 at 13:01 Peter Stephenson <[email protected]> wrote: >> >> On Sun, 2025-10-26 at 10:16 +0100, Alexey Sukhoguzov wrote: >> > Please help me to clarify this situation: >> > >> > $ (echo foo) > ${myvar:=tmpfile} >> > $ echo ${myvar:-still unset} >> > still unset >> >> It's a bit of a headbanger, and I don't see it explicitly documented, but >> the main point of what's going on is that whenever zsh executes a command >> that's not going to run in the main shell, any redirection is done after >> the fork. This is really for convenience > > I'm not sure why the parameter expansion happens post-fork, though. The redirect, sure. But the parameter expansion should presumably happen before any of that stuff as part of parsing the command line. Why isn't the assignment already done by the time it forks the subshell? There's a more subtle reason than just code convenience: The redirection and the parameter substitution are semantically part of the whole command including the subshell. Consider that if you wrote $ (echo foo) > ${myvar:=tmpfile} & you would not (or at least I would not) expect the parameter substitution to happen before the command was backgrounded. This especially matters if you consider further expansions within the parameter substitution: $ (echo foo) > ${myvar:=$(sleep 30; echo tmpfile)} & This was actually fixed several years later (a few years ago now) for function definitions: $ tempfoo() { echo foo } > ${myvar:=tmpfile} The redirection and the substitution are both part of the function's definition, not part of the creation of the function.