Question about command execution in powershell

Tag: powershell Author: xiaoneiku Date: 2009-08-26

Can someone help me explain what is happening here? Sorry if this is a basic question, I simplified it from a pipeline expression I'm trying to write:

$foo = pwd
$cmd = "dir"

& $cmd $foo #Works

dir $foo  #Works

& "dir $foo" #Error

*The term 'dir C:\' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.

At line:1 char:2 + & <<<< "dir $foo"*

dir pwd #Error

*Get-ChildItem : Cannot find path 'C:\pwd' because it does not exist.

At line:1 char:4 + dir <<<< pwd*

I would expect all four of these to yield the same results

What is the purpose of $cmd = "dir"? It doesn't look like you're using $cmd anywhere.
sorry copy paste error. $dir is supposed to be $cmd
You can always get these sorts of problems to work by using Invoke-Expression, or wrapping with () or $() or @(). For example, to make the 4th one work: dir (pwd) dir $(pwd) dir $pwd (not sure why this one works...) invoke-expression "dir (pwd)" Don't ask "why" too much with Powershell, it's not worth the headache, just remember the set of things that could possibly work and experiment.

Best Answer

Expressions in quotes are interpreted as a single argument. In the third command, the shell is interpreting it as a request for the command "dir C:\" with no arguments, rather than a request for the command "dir" with an argument of "C:\".

Other Answer1

If you want to "execute" a string containing arbitrary script use the Invoke-Expression cmdlet e.g.:

Invoke-Expression "dir $foo"

comments:

Keith I'm reading the section from your ebook that talks about the different parsing modes (Item 7 Page 31) it is helpful; but I haven't quite got it sorted out yet. I thought the & operator was a short cut for Invoke-Expression; but it appears there are some subtle differences do you know where I can find out more? I tried the msdn docs; but that didn't add a whole lot.
& is the call operator. It just interprets the string that follows it to be the "name" of a command. So you can't include arguments in the string. BTW you can do the same with dot e.g. ". $foo". The difference is that & will cause the command to execute in a new nested scope whereas dotting executes the command in the current scope. This usually only matters though when the command is the name or path of a script file.