So I think what is tripping you here is the command format where the first word(s) in the command are a variable assignment (which the shell determines based on the presence of a =
.)
In those cases, the shell will evaluate those assignments, but it will only export those variables in the command that it is running. In particular, the shell itself won't have access to those variables.
This is useful for running commands or scripts that are affected by environment variables, in which case you don't need to export them in a shell and can just set them as "one-offs" for that single execution.
Let's break down your commands and explain them one by one:
pwd echo 'aaa' # /home/me
Ok, so this is running the pwd
command and passing it two arguments, echo
and aaa
. But pwd
doesn't take arguments, so it's just ignoring those two and printing the local directory.
val=pwd echo 'aaa' # aaa
So as I explained, this performs the variable assignment, setting $val
to contain the string pwd
and then executes the echo
command with the aaa
argument. The $val
variable is available only to the echo
command and not to the shell itself! The echo
command doesn't really do anything with that variable, so it simply goes ahead and prints aaa
. After this command is finished, the $val
variable is not defined in the shell.
val=pwd echo 'aaa'$val # aaa
So, again, similar to the command above. This one gets tricky, since you might expect the final $val
to get expanded. But variables are expanded by the shell, not by the commands. And, as explained, the shell doesn't really see $val
which is set to pwd
, only the command (in this case, echo
) does, so $val
gets expanded to an empty string, and this is exactly equivalent to the above.
val=pwd echo 'aaa' && echo $val # aaa <and an empty line>
And one more time, $val
is not available after the first echo
command completes, so the second echo $val
will print nothing (just the blank line), as $val
was never really set in the shell itself throughout this execution.
If you want to set $val
in the shell, then you need to make that assignment a standalone, without any commands. For instance, this behaves differently from the above:
$ val=pwd; echo 'aaa' && echo $val
aaa
pwd
Since val=pwd
is followed by a ;
, then the shell considers it a command on its own and will set $val
in the current shell, so the echo $val
will work as you expect.
(Note that there's one more difference here, since with val=pwd; ...
, the variable $val
is not really exported, so echo
will not see that variable in its environment, while with val=pwd echo ...
it would get exported, but then in that case, it is not available in the shell.)
And considering you're using pwd
, I wonder if what you wanted was to store the output of that command in the variable... In which case, you need to use shell command substitution, either using backticks, or better yet, surrounding the command with $(
and )
.
So one final example here:
$ val=$(pwd); echo 'aaa' && echo $val
aaa
/home/me
Or:
$ val=$(pwd) && echo 'aaa' && echo $val
aaa
/home/me
(There's a subtle difference here, where the latter will break execution if the command inside the substitution, in this case pwd
, fails and exits with a non-zero status, in which case the following commands will not be executed. When using ;
that's not the case, the following commands are executed even if the first one fails.)
I hope this explains what you weren't understanding about these commands!
&&
. – Gordon Davisson Jul 26 '18 at 06:36pwd
(with too many arguments). The rest is a syntax error due to the unterminated command substitution (unbalanced backticks). (Now edited by Filipe Brandenburger). – Kusalananda Jul 26 '18 at 06:45setup.sh
, you will get what I posed here... Seriously I got no idea why it wrote such a code. – Yves Jul 26 '18 at 07:11