2009-08-15 3 views
5

In Windows PowerShell, sto tentando di memorizzare un comando di spostamento in una stringa e quindi eseguirlo. Qualcuno può dirmi perché questo non funziona?Perché non posso eseguire un comando con argomenti da una stringa in 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> 

Viene visualizzato questo errore quando si memorizza un comando con argomenti. Come posso superare questa limitazione?

risposta

10

Dalla aiuto (about_Operators):

 
& Call operator 
    Description: Runs a command, script, or script block. Because the call 
    operator does not parse, it cannot interpret command parameters.

È possibile utilizzare un blocco di script, invece di una stringa:

$s = { mv sa.csproj sb.csproj } 
& $s 

oppure è possibile utilizzare Invoke-Expression:

Invoke-Expression $str 

o

iex $str 

Al contrario di &, Invoke-Expressionfa analizzare il contenuto della stringa, in modo da poter inserire qualsiasi cosa, non solo un singolo comando.

+0

Grazie, pensi che si può spiegare (o link) una spiegazione di ciò che il carattere & fa? –

+2

'&' è per l'esecuzione di un singolo comando, script o scriptblock, proprio come gli stati della guida. Non esegue alcun parsing quindi accetta solo un singolo argomento che quindi si presume sia un comando invokable. Se si desidera aggiungere parametri, quindi eseguire il wrapping della chiamata in uno script o un blocco di script o utilizzare 'Invoke-Expression'. Puoi trovare la pagina di aiuto che descrive gli operatori digitando 'help about_operators' in Powershell. – Joey

5

Tutti i suggerimenti di Johannes sono chiari, ma voglio far sapere alla gente che nella V2 c'è un'altra opzione. Hai messo il comando in una stringa come prima, ma si mettono i parametri in una tabella hash e richiama utilizzando & es .:

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

Questo utilizza una nuova funzionalità denominata V2 splatting. È un po 'come usare un file di risposta per un comando ma si mettono i parametri in un hashtable anziché in un file.

Nota: si può anche mettere i parametri in un array che collegare i parametri "di posizionale" piuttosto che per nome es:

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

Esso non può corrispondere esattamente il problema del PO, ma si tratta di una trucco che vale la pena conoscere.

2

ho dovuto rispondere a una domanda simile un po 'indietro su invocando un programma esterno, dopo la costruzione di un elenco di argomenti:

controllato e sembra che usando . $program $argString o & $program $argString non funziona se $argString contiene più argomenti . Gli operatori . e & eseguono semplicemente una chiamata diretta, passando l'intero $argString come un singolo argomento.

Invece di usare [string]$argString e fare $argString += "-aaa `"b b b`"", è possibile modificare a [string[]]$argArray e utilizzare $argArray += @('-aaa', 'b b b'), che funzionerà e sarà fuggire automaticamente le stringhe se necessario.

È inoltre possibile utilizzare $process = [Diagnostics.Process]::Start($program, $argString). Ciò renderà più semplice tracciare i progressi dell'esecuzione, ma sarà più difficile recuperare qualsiasi output di testo.

Oppure è possibile inserire tutto in una stringa e utilizzare Invoke-Expression "$program $argString", che analizzerà l'intera stringa come un comando ed eseguirà correttamente.

Come accennato Keith, splatting è un'altra buona opzione in PowerShell 2.