Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Parameter assignment in a redirection word



On Sun, Oct 26, 2025 at 10:17 AM Alexey Sukhoguzov <mail@xxxxxxxxx> wrote:
>
> Hi,
>
> Please help me to clarify this situation:
>
>         $ (echo foo) > ${myvar:=tmpfile}
>         $ echo ${myvar:-still unset}
>         still unset
>
> Why $myvar is set in a subshell instead of a parent process in this
> case?  I was unable to find where it's documented, but I've checked
> some other shells, and of course it turned out that zsh is not alone
> here, at least bash is doing the same.  OTOH, FreeBSD sh, oksh and
> dash all seem to set the variable in a parent.  I was thinking that
> the latter is the only expected behavior, just like in
>
>         $ echo foo > ${myvar:=tmpfile}
>         $ echo ${myvar:-still unset}
>         tmpfile
>
> which, by the way, works identically in all the shells that I've
> tested.  But after I tried
>
>         $ (echo foo) | tee ${myvar:=tmpfile}
>
> and found that $myvar is set by a parent in zsh only, I'm not sure
> what to expect any longer.  Could anyone shed some light on what's
> going on here?

You'll find the same result if you use an external command as well, eg
% /bin/echo > ${myvar:=tmpfile}

You can force the expansion to happen in the current shell by using
% { /bin/echo } > ${myvar:=tmpfile}
or in your example
% { ( echo ) } > ${myvar:=tmpfile}

This isn't directly related, but the manual does have this to say
about function definitions with redirections,

              In  any  of  the  forms  above, a redirection may appear
outside the function
              body, for example

                     func() { ... } 2>&1

              The redirection is stored with the function and applied
whenever the function
              is  executed.  Any variables in the redirection are
expanded at the point the
              function is executed, but outside the function scope.

and in the case that the command is not found, the
command_not_found_handler hook function is also run in the forked
subshell (this is a bit more obvious though, we have to fork before we
can try to exec the given command).

-- 
Mikael Magnusson




Messages sorted by: Reverse Date, Date, Thread, Author