7

From man bash:

A simple command is a sequence of optional variable assignments
followed by blank-separated words and redirections, and
terminated by a control operator. The first word specifies the
command to be executed, and is passed as argument zero. The
remaining words are passed as arguments to the invoked command.

So it's perfectly legal to write:

foo=bar echo $foo

but it doesn't work as I expect (it prints just a newline). It's quite strange to me since:

$ foo=bar printenv
foo=bar
TERM=rxvt-unicode
[...]

Could someone please explain me where I'm doing wrong?

6

This happens because variable expansion is done before the command is run. At the time variable expansion happens, foo is not set, so it expands to the empty string. The command then runs, setting foo.

  • 1
    Also, note that since foo is set as a prefix to the echo command, it's only set for that command (and not for subsequent commands). Compare with foo=bar eval 'echo eval sees $foo'; echo echo sees $foo (here, since $foo is expanded within the eval command, the value will be substituted there, but not for the next echo command). – Gordon Davisson Oct 25 '10 at 19:30
  • 1
    This is an assignment in the child's environment (i.e. echo in the original question or eval in Gordon's example). Variable assignments in the child's environment do not affect variable values in the parent's. foo=bar eval 'foo=$foo'; echo $foo outputs only a newline. – Dennis Williamson Oct 25 '10 at 20:55
  • From man bash: "If no command name results, the variable assignments affect the current shell environment. Otherwise, the variables are added to the environment of the executed command and do not affect the current shell environment. If any of the assignments attempts to assign a value to a readonly variable, an error occurs, and the command exits with a non-zero status." – Dennis Williamson Oct 25 '10 at 21:02
1

If you are doing foo=bar and echo $foo on one line, it will not work. You will have to do one of three things.

  1. Run them as seperate commands. i.e: foo=bar Enter echo $foo

  2. Run them on one line, but with a semicolon between the two. ie: foo=bar; echo $foo

  3. Same as #2, but with double-ampersands. ie: foo=bar && echo $foo

The difference between 2 and 3 is that 3 will only execute echo $foo if foo=bar succeeded.

  • Thanks, but I know how to work around to the problem. I only was interested on the example I provided. – cYrus Oct 25 '10 at 20:34
  • +1: Nice set of alternatives though. This might come handy to someone. – cYrus Oct 25 '10 at 20:48
0

Try:

foo=bar; echo $foo
       ^

Mind the ; since you're trying to fit two seperate commands on a single line. They don't work together by default.

0

A proper way to do it would be:

foo=bar sh -c 'echo $foo'

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.