在windows powershell中,我试图在一个字符串中存储一个move命令,然后执行它。有人能告诉我为什么这不起作用吗?
PS C:\Temp\> dir
Directory: Microsoft.PowerShell.Core\FileSystem::C:\Temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 8/14/2009 8:05 PM 2596 sa.csproj
-a--- 8/15/2009 10:42 AM 0 test.ps1
PS C:\Temp> $str = "mv sa.csproj sb.csproj"
PS C:\Temp> &$str
The term 'mv sa.csproj sb.csproj' is not recognized as a cmdlet, function, operable program, or script file. Verify the
term and try again.
At line:1 char:2
+ &$ <<<< str
PS C:\Temp>
存储带参数的任何命令时出现此错误。我如何克服这个限制?
答案 0 :(得分:11)
来自帮助(about_Operators):
& Call operator Description: Runs a command, script, or script block. Because the call operator does not parse, it cannot interpret command parameters.
您可以使用脚本块而不是字符串:
$s = { mv sa.csproj sb.csproj }
& $s
或者您可以使用Invoke-Expression
:
Invoke-Expression $str
或
iex $str
与&
相比,Invoke-Expression
会解析字符串内容,因此您可以在其中放置任何内容,而不仅仅是单个命令。
答案 1 :(得分:5)
约翰内斯的所有建议都在现场,但我想让人们意识到在V2中有另一种选择。您将命令放在字符串中,但是您将参数放在哈希表中并使用&amp; e.g:
$cmd = 'mv'
$params = @{Path = 'log.txt'; Destination = 'log.bak'}
&$cmd @params
这使用了一个名为splatting的新V2功能。它有点像为命令使用响应文件,但是您将参数放在哈希表而不是文件中。
注意:您也可以将参数放在一个数组中,该数组将插入“按位置”而不是按名称插入参数,例如:
$cmd = "cpi"
$params = ('log.txt', 'log.bak')
&$cmd @params
它可能不完全符合OP的问题,但这是一个值得了解的技巧。
答案 2 :(得分:2)
在构建参数列表后,我不得不回答一个类似的问题:关于调用外部程序:
选中,如果
. $program $argString
包含多个参数,则使用& $program $argString
或$argString
似乎不起作用。.
和&
运算符只是直接调用,将整个$argString
作为单个参数传递。您可以将其更改为
[string]$argString
并使用$argString += "-aaa `"b b b`""
,而不是使用[string[]]$argArray
并使用$argArray += @('-aaa', 'b b b')
,这将有效,并会根据需要自动转义字符串。您也可以使用
$process = [Diagnostics.Process]::Start( $program, $argString )
。这样可以更轻松地跟踪执行进度,但更难以检索任何文本输出。或者您可以将所有内容放在字符串中并使用
Invoke-Expression "$program $argString"
,它将整个字符串解析为命令并正确执行。
正如Keith所述,splatting是PowerShell 2中另一个不错的选择。