15

If I do this:

SUMAN_DEBUG=foo echo $SUMAN_DEBUG

I get no output

but if I do:

SUMAN_DEBUG=foo && echo $SUMAN_DEBUG

then I get

"foo"

why is that?

2 Answers2

5

[This answer is not correct. The problem is due to variable expansions occurring before variable assignments on the command line. See comments below. Also, this question was declared a duplicate and there is an excellent discussion in the original question. -gt]

SUMAN_DEBUG=foo is a local environment variable assignment for a local variable that exists only for the command it prefaces. In your second case, there is no command because the && initiates a list of command where in your case, the first command is null (so the environment variable has no command to affect) and the second is executed but has no environment variable set for it.

You could add export to the assignment so that the variable would become a global environment variable. But then it would persist after the list of commands is complete.

Another option is to put the entire command list in parenthesis to execute it in a subshell:

(export SUMAN_DEBUG=foo && echo $SUMAN_DEBUG)

In this case, the persistent environment variable would be set in a subshell and that environment would disappear when the subshell completed its work).

See the Bourne-again Shell Manual, lists section and the section on Environment for more.

  • It looks like this also works well without the export: (SUMAN_DEBUG=foo && echo $SUMAN_DEBUG) and keeps it in the scope of the command sequence – groovenectar Mar 27 '19 at 15:30
  • 3
    I'm afraid that's wrong. The first one doesn't work because command arguments are expanded before variable assignment happens. The second one works because SUMAN_DEBUG=foo performs an assignment in the scope of the current shell (my terminology may be imprecise here). @groovenectar's answer seems like a way to go. Your solution with export is useful if the variable is intended to be referenced from a subshell (e.g. you invoke a script that expects that variable to be set). – tonytony Jul 26 '19 at 09:42
  • My answer is indeed wrong. Thanks for pointing it out. I re-ran my tests and realized that one of these forms sets the variable as a side-effect so that later tests showed it expanding because of leakage between test cases. I am still not satisfied with the generally accepted answer because I routinely pass variables to apps this way and it works. I wonder if echo being a built-in results in slightly different precedence rules being invoked. – Greg Tarsa Jul 27 '19 at 15:06
  • This answer should either be updated or removed. – fgblomqvist Sep 29 '21 at 10:57
1

In command line you need to separate commands using either ; or &&. Space it is just not a delimiter for CLI commands.

With && the second command will be executed if the first command exits successfully (exit code 0).

With ; the second command will be executed no matter what is the exit status of first command.

Test:

# a1;echo hello
bash: a1: command not found
hello
# a1 && echo hello
bash: a1: command not found

In scripts the first command and the second command is separated by a new line \n character, also recognized by bash.

  • 4
    A variable assignment is not a command. The reason for OP's behavior is because the expansion happens before the assignment. – jordanm Dec 11 '16 at 02:12