tags:

views:

26

answers:

1

According to section 3.7.1 of the Bash manual, variable assignments at the beginning of a command line should be visible to the invoked program.

e.g.

DIR=/tmp ls $DIR

should behave as if I've typed "ls /tmp" - and the variable DIR should not persist after executing the command.

Cygwin Bash (GNU bash, version 3.2.51(24)-release (i686-pc-cygwin)) appears not to do this - the above command behaves as if $DIR is not defined. This is confirmed by other tests such as "DIR=/tmp echo $DIR", "DIR=/tmp set" etc.

Note that adding a semicolon works ("DIR=/tmp ; ls $DIR"), but leaves the variable defined after the command.

Why is this not working as expected?

+3  A: 

It does work - but not in the context that you are trying to make it work.

DIR=/tmp ls $DIR

The environment variable DIR is set for ls - but is not set when the shell expands the $DIR of the command. This is the way the Bourne shell behaved; it is the way its successors such as the Korn shell and Bash behave.

You could see that DIR is set by changing ls $DIR to env; that would show the environment of an external (not built-in) command.

In this example, think about it for a moment: what you've typed is 9 extra characters compared with:

ls /tmp

If you must have it set and removed, then this does the trick:

(DIR=/tmp; ls $DIR)

The variable is set before the shell evaluates ls $DIR, but the whole command is run in a sub-shell so it has no impact on the invoking shell.

Jonathan Leffler
Ah, that's why I need the semicolon when giving a big bash command to xargs.
Matt Kane
Of course I've typed 9 extra characters - to create the example.
Jeremy
But you're correct - the variable will be set _after_ the rest of the command line is expanded.
Jeremy
Next question: why is the variable visible to 'env' but not to 'set'?
Jeremy
Answering my own question: Because 'env' is a separate program, while 'set' is a builtin. As the manual describes, DIR will be added to the environment of the executed command and does not affect the current environment. In this context, a builtin is not an 'executed command', but uses the current environment.
Jeremy