I'm learning about bash and zsh. One command I came across was exec
. I know that it will replace the current process with the supplied command. By what I have read over the internet, the local variables will not be inherited in the replaced process of exec. I tested it and failed. I am using zsh 5.9
on MacOS 14
.
Here is what I wrote,
> a=2
> exec echo $a
2
process exited...
I thought it might be due to parameter expansion and I tried the following
> a=2
> exec echo '$a'
$a
process exited...
Since it printed $a
, I'm guessing that parameter expansion didn't happen. Otherwise, the single quotes would have been removed and $a
would have been treated as an expansion instead of a string.
To further verify if the variable was inherited or not, I used the declare
command. The output is as follows
> aa=2
> exec declare -p | grep aa
typeset aa=2
Even this shows the local variable.
Since exec
doesn't inherit the local variables, why is it happening? I don't think it is only related to zsh.
Yes, $a
is expanded first, then exec
receives the arguments echo
and 2
.
With single quotes, exec
receives the arguments echo
and $a
.
In bash
, exec declare -p
should fail, as declare
is a shell built-in command, not an executable.
In zsh
, using the built-in declare
does not cause exec
to fail, but is executed in the current shell, and then the current shell exits. (Because you used a pipeline, though, the current shell is a subshell that "copied" the parent, and that's what exits.) You can consider that inheritance if you like, but it's special zsh
behavior, not related to the POSIX definition of exec
.
From man zshbuiltins
:
exec [ -cl ] [ -a argv0 ] [ command [ arg ... ] ]
Replace the current shell with
command
rather than forking. Ifcommand
is a shell builtin command or a shell function, the shell executes it, and exits when the command is complete.