2009-08-15 6 views
5

Windowsのpowershellでは、私は文字列にmoveコマンドを格納して、それを実行しようとしています。誰かがなぜこれがうまくいかないのか教えてもらえますか?PowerShellの文字列の引数を使用してコマンドレットを実行できないのはなぜですか?

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> 

引数を含むコマンドを格納するときにこのエラーが発生します。この制限をどのように克服できますか?ヘルプ(about_Operators)から

答えて

10

 
& 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つのコマンドだけでなく、そこに何かを入れることができます。

+0

おかげでしょうか? –

+2

'&'は、ヘルプ状態と同様に、単一のコマンド、スクリプト、スクリプトブロックを実行するためのものです。これは構文解析を行わないので、呼び出し可能なコマンドとみなされる単一の引数のみを受け入れます。パラメータを追加する場合は、スクリプトまたはスクリプトブロックで呼び出しをラップするか、 'Invoke-Expression'を使用します。 powershellに 'help about_operators'と入力すると、演算子を説明するヘルプページが表示されます。 – Joey

5

ヨハネスのすべての提案は掲載されていますが、V2では別の選択肢があることを皆さんに知らせたいと思います。あなたは前のように、文字列内のコマンドを入れていますが、ハッシュテーブルにパラメータを入れて、これは、スプラッティングと呼ばれる新しいV2の機能を使用しています&例えば:

$cmd = 'mv' 
$params = @{Path = 'log.txt'; Destination = 'log.bak'} 
&$cmd @params 

を使用して起動します。レスポンス・ファイルをコマンドに使用するのと似ていますが、ファイルの代わりにハッシュ・テーブルにパラメータを入れます。

注:また名前などによってではなく、「位置で」パラメータにプラグインされますアレイ内でパラメータを置くことができます。

$cmd = "cpi" 
$params = ('log.txt', 'log.bak') 
&$cmd @params 

まさにOPの問題に適合しないかもしれないが、それはありますトリック知る価値がある。

2

私は、引数のリストを構築した後、外部プログラムを呼び出すことについて、しばらく前に同様の質問に答える必要がありました:チェック

$argStringは複数の引数が含まれている場合. $program $argString& $program $argStringを使用して動作しないように見えます。 .&オペレータは、ただ1つの引数として$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として

は、スプラッティングはあなたが&文字が何をするかの説明を説明する(あるいはリンクする)ことができると思います、PowerShellの別の良いオプション2.