TL;DR: The first assignment fixes which variable z
refers to. The second assignment changes the value of that variable. The second call to declare
is essentially a no-op; you've already set the nameref
attribute on z
; doing so a second time changes nothing.
The first time you use declare
, z
is uninitialized and undefined. The first assignment to z
(whether in the call to declare
or subsequent to it) determines which variable z
refers to.
$ declare -n z
$ echo $z
$ z=somevalue
$ declare -p z
declare -n z=somevalue
echo $z
at this point produces no value because somevalue
itself is undefined.
Your second call to declare doesn't really do anything to z
:
$ declare -n z
$ declare -p z
declare -n z=somevalue
It's still a reference to the variable somevalue
. But now your second assignment to z
does something different: it assigns a value to the variable somevalue
, so that now when you do echo $z
, you see the value of the variable somevalue
, just as if you had written echo $somevalue
.
It's a little less confusing if we use a different value for the two assignments, so we can distinguish between the referenced variable and its value.
$ declare -n z
$ z=foo
$ declare -p z
declare -n z=foo
$ z=9
$ echo $foo
9