1
  1. When a shell runs an external executable as a command, we can pass environment variables into the executable.

    $ var=3 /bin/echo `$var`
    
    $ var=3 bash -c "/bin/echo '$var'"
    

    both don't output anything.

  2. When a program is executed by exec, I want to see if environment variable also works:

    $ bash
    $ unset var; 
    $ var=3 exec /bin/echo '$var'
    $var
    $ exec var=3 /bin/echo '$var'
    bash: exec: var=3: not found
    

To prevent variable expansion, I use single quote around $var. The protection seems a little too much.

Why is this environment variable not set up in the above cases?

Can I make environment variables work for a program executed by exec?

Thanks.

3
  • All your problems are related to quoting, not environment.

    1. Environment for a command.

      When a shell runs an external executable as a command, we can pass environment variables into the executable.

    Yes, that's a way to set environment variables for a command, external or otherwise.

    But what you are missing in this line[a]:

    $ var=3 /bin/echo "$var"
    

    Is that the shell expands the variable when building the arguments, and, if the variable var is not set in the shell which starts the command, this is what is actually executed:

    $ var=3 /bin/echo ""
    

    To actually see the present shell expansion, run this:

    $ var=RunningShell ;   var=3 /bin/echo "$var"
    RunningShell
    

    One (often times insecure) way to delay the evaluation of the variable is:

    $ var=3 eval /bin/echo '"$var"'
    3
    

    On the second example you have the quotes exchanged:

    $ var=3 bash -c "/bin/echo '$var'"
    

    Prints nothing as the actual command line becomes:

    $ var=3 bash -c "/bin/echo ''"
    

    As the value of the (unset) variable $var is expanded. You probably meant this:

    $ var=thisis3 bash -c '/bin/echo "$var"'
    thisis3
    

    In which case the single quotes prevent the expansion of the variable by the executing shell, leaving the expansion to the executed shell (bash -c).

    • Use env to actually see the environment.

      1. When a program is executed by exec, I want to see if environment variable also works:

    Do not exec in your present shell as it will close the running shell.
    You may do this to avoid closing the running shell:

    $ var=3 exec /bin/echo \$var | cat
    $var
    

    As the closed shell will be the one that would be closed anyway, the first sub-shell of a pipe.

    But that will not show you the value of var in the environment. To see variables in the environment, use the command to see the environment:

    $ var=3 env | grep var
    var=3
    

[a] The command you wrote had backquotes `, changing them to single quotes will avoid the expansion of the variable and will print $var.:

$ var=3 /bin/echo '$var'
$var
5

Remember that parameter expansion doesn’t happen magically, you need a shell to do it for you.

var=3 /bin/echo `$var`

I’m not sure what you’re trying to do with that one, back-ticks aren’t appropriate here (they execute a command and are replaced with its output).

var=3 bash -c "/bin/echo '$var'"

doesn’t work because parameter expansion occurs before the assignment, so the current shell changes "/bin/echo '$var'" to /bin/echo '' (assuming var is undefined), and the child shell is run with

/bin/echo ''

Try

var=3 bash -c 'echo $var'

instead: the single quotes here protect the argument from the current shell, and the new shell is run with

echo $var

which it will process as you’d expect.

In your second point, my initial comment still applies. If you want to play around with the environment and see what happens, run env and filter its output instead:

var=3 env | grep var
var=3 exec env | grep var
  • Thanks. i noticed something perhaps incorrect. and changed it. – Tim Aug 8 '17 at 17:38
  • @Tim could you explain your change? I think it’s wrong... – Stephen Kitt Aug 8 '17 at 17:39
  • When a shell sees var=3 bash -c "/bin/echo '$var'", the single quotes within the double quotes are literal, so don't prevent parameter expansion $var in the shell, where var is unset. So the child shell which the shell forks to execute the double quoted content sees /bin/echo ''. See Arrow's answer. – Tim Aug 8 '17 at 17:44
  • Still not correct. the current shell changes "/bin/echo '$var'" to /bin/echo '' (assuming var is undefined). parameter expansion happens before quote removal. – Tim Aug 8 '17 at 18:59
  • @Tim huh, yes, that’s what I meant to write :-/. – Stephen Kitt Aug 8 '17 at 19:46

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.