带有 Robocopy 和参数传递的 Powershell
Powershell with Robocopy and Arguments Passing
我正在尝试编写一个使用 robocopy
的脚本。如果我只是手动执行此操作,我的命令将是:
robocopy c:\hold\test1 c:\hold\test2 test.txt /NJH /NJS
但是,当我从 powershell 执行此操作时,例如:
$source = "C:\hold\first test"
$destination = "C:\hold\second test"
$robocopyOptions = " /NJH /NJS "
$fileList = "test.txt"
robocopy $source $destination $fileLIst $robocopyOptions
我得到:
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : Fri Apr 10 09:20:03 2015
Source - C:\hold\first test\
Dest - C:\hold\second test\
Files : test.txt
Options : /COPY:DAT /R:1000000 /W:30
------------------------------------------------------------------------------
ERROR : Invalid Parameter #4 : " /NJH /NJS "
但是,如果我将 robocopy 命令更改为
robocopy $source $destination $fileLIst /NJH /NJS
一切顺利。
所以,我的问题是,我如何传递一个字符串作为我的 robocopy 命令选项(并且,在更大的意义上,对任何给定的外部命令执行相同的操作)
Start robocopy -args "$source $destination $fileLIst $robocopyOptions"
或
robocopy $source $destination $fileLIst $robocopyOptions.split(' ')
你不能使用字符串以那种方式传递选项,因为当你写
robocopy $source $destination $fileList $robocopyOptions
PowerShell 会将最后一个变量 ($robocopyOptions
) 计算为单个字符串并引用它。这意味着 robocopy 将在其命令行上获得 "/NJH /NHS"
(单个字符串,带引号)。 (显然不是本意。)
有关如何解决此类问题的详细信息,请参阅此处:
http://windowsitpro.com/powershell/running-executables-powershell
文章包含以下功能:
function Start-Executable {
param(
[String] $FilePath,
[String[]] $ArgumentList
)
$OFS = " "
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $FilePath
$process.StartInfo.Arguments = $ArgumentList
$process.StartInfo.UseShellExecute = $false
$process.StartInfo.RedirectStandardOutput = $true
if ( $process.Start() ) {
$output = $process.StandardOutput.ReadToEnd() `
-replace "\r\n$",""
if ( $output ) {
if ( $output.Contains("`r`n") ) {
$output -split "`r`n"
}
elseif ( $output.Contains("`n") ) {
$output -split "`n"
}
else {
$output
}
}
$process.WaitForExit()
& "$Env:SystemRoot\system32\cmd.exe" `
/c exit $process.ExitCode
}
}
此函数可以让您 运行 在当前控制台中执行一个可执行文件 window 并且还可以让您构建一个字符串参数数组以传递给它。
所以在你的情况下你可以像这样使用这个函数:
Start-Executable robocopy.exe $source,$destination,$fileList,$robocopyOptions
使用数组,卢克。如果您指定一个值数组,PowerShell 会自动将它们扩展为单独的参数。根据我的经验,这是最可靠的方法。而且它不需要您弄乱 Start-Process
cmdlet,在我看来,这对于此类任务来说太过分了。
这个技巧来自我见过的关于 PowerShell 对外部可执行文件的行为的最好的文章:PowerShell and external commands done right.
示例:
$source = 'C:\hold\first test'
$destination = 'C:\hold\second test'
$robocopyOptions = @('/NJH', '/NJS')
$fileList = 'test.txt'
$CmdLine = @($source, $destination, $fileList) + $robocopyOptions
& 'robocopy.exe' $CmdLine
将选项放在单独的参数中对我有用。使用 Robocopy 进行复制,不包括任何 CSV 文件。
$roboCopyPath = $env:ROBOCOPY_PATH
$otherLogsPath = [System.IO.Path]::Combine($basePath, "Logs-Other")
$atrTestResults = [System.IO.Path]::Combine($Release, $BuildNumber)
$ResultsSummary = [System.IO.Path]::Combine($basePath, "Result")
$robocopyOptions = @("/log:$otherLogsPath\robocopy.log", '/xf', '*.csv')
$CmdLine = @($atrTestResults, $ResultsSummary) + $robocopyOptions
&$roboCopyPath $CmdLine
我正在尝试编写一个使用 robocopy
的脚本。如果我只是手动执行此操作,我的命令将是:
robocopy c:\hold\test1 c:\hold\test2 test.txt /NJH /NJS
但是,当我从 powershell 执行此操作时,例如:
$source = "C:\hold\first test"
$destination = "C:\hold\second test"
$robocopyOptions = " /NJH /NJS "
$fileList = "test.txt"
robocopy $source $destination $fileLIst $robocopyOptions
我得到:
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : Fri Apr 10 09:20:03 2015
Source - C:\hold\first test\
Dest - C:\hold\second test\
Files : test.txt
Options : /COPY:DAT /R:1000000 /W:30
------------------------------------------------------------------------------
ERROR : Invalid Parameter #4 : " /NJH /NJS "
但是,如果我将 robocopy 命令更改为
robocopy $source $destination $fileLIst /NJH /NJS
一切顺利。
所以,我的问题是,我如何传递一个字符串作为我的 robocopy 命令选项(并且,在更大的意义上,对任何给定的外部命令执行相同的操作)
Start robocopy -args "$source $destination $fileLIst $robocopyOptions"
或
robocopy $source $destination $fileLIst $robocopyOptions.split(' ')
你不能使用字符串以那种方式传递选项,因为当你写
robocopy $source $destination $fileList $robocopyOptions
PowerShell 会将最后一个变量 ($robocopyOptions
) 计算为单个字符串并引用它。这意味着 robocopy 将在其命令行上获得 "/NJH /NHS"
(单个字符串,带引号)。 (显然不是本意。)
有关如何解决此类问题的详细信息,请参阅此处:
http://windowsitpro.com/powershell/running-executables-powershell
文章包含以下功能:
function Start-Executable {
param(
[String] $FilePath,
[String[]] $ArgumentList
)
$OFS = " "
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $FilePath
$process.StartInfo.Arguments = $ArgumentList
$process.StartInfo.UseShellExecute = $false
$process.StartInfo.RedirectStandardOutput = $true
if ( $process.Start() ) {
$output = $process.StandardOutput.ReadToEnd() `
-replace "\r\n$",""
if ( $output ) {
if ( $output.Contains("`r`n") ) {
$output -split "`r`n"
}
elseif ( $output.Contains("`n") ) {
$output -split "`n"
}
else {
$output
}
}
$process.WaitForExit()
& "$Env:SystemRoot\system32\cmd.exe" `
/c exit $process.ExitCode
}
}
此函数可以让您 运行 在当前控制台中执行一个可执行文件 window 并且还可以让您构建一个字符串参数数组以传递给它。
所以在你的情况下你可以像这样使用这个函数:
Start-Executable robocopy.exe $source,$destination,$fileList,$robocopyOptions
使用数组,卢克。如果您指定一个值数组,PowerShell 会自动将它们扩展为单独的参数。根据我的经验,这是最可靠的方法。而且它不需要您弄乱 Start-Process
cmdlet,在我看来,这对于此类任务来说太过分了。
这个技巧来自我见过的关于 PowerShell 对外部可执行文件的行为的最好的文章:PowerShell and external commands done right.
示例:
$source = 'C:\hold\first test'
$destination = 'C:\hold\second test'
$robocopyOptions = @('/NJH', '/NJS')
$fileList = 'test.txt'
$CmdLine = @($source, $destination, $fileList) + $robocopyOptions
& 'robocopy.exe' $CmdLine
将选项放在单独的参数中对我有用。使用 Robocopy 进行复制,不包括任何 CSV 文件。
$roboCopyPath = $env:ROBOCOPY_PATH
$otherLogsPath = [System.IO.Path]::Combine($basePath, "Logs-Other")
$atrTestResults = [System.IO.Path]::Combine($Release, $BuildNumber)
$ResultsSummary = [System.IO.Path]::Combine($basePath, "Result")
$robocopyOptions = @("/log:$otherLogsPath\robocopy.log", '/xf', '*.csv')
$CmdLine = @($atrTestResults, $ResultsSummary) + $robocopyOptions
&$roboCopyPath $CmdLine