简体   繁体   English

带有 Robocopy 和参数传递的 Powershell

[英]Powershell with Robocopy and Arguments Passing

I'm trying to write a script that uses robocopy .我正在尝试编写一个使用robocopy的脚本。 If I were just doing this manually, my command would be:如果我只是手动执行此操作,我的命令将是:

robocopy c:\hold\test1 c:\hold\test2 test.txt /NJH /NJS

BUT, when I do this from powershell, like:但是,当我从 powershell 执行此操作时,例如:

$source = "C:\hold\first test"
$destination = "C:\hold\second test"
$robocopyOptions = " /NJH /NJS "
$fileList = "test.txt"

robocopy $source $destination $fileLIst $robocopyOptions

I get:我得到:

-------------------------------------------------------------------------------
   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 "

However, if I change the robocopy command to但是,如果我将 robocopy 命令更改为

robocopy $source $destination $fileLIst  /NJH /NJS 

everything runs successfully.一切顺利。

So, my question is, how can I pass a string as my robocopy command options (and, in a larger sense, do the same for any given external command)所以,我的问题是,如何将字符串作为我的 robocopy 命令选项传递(并且,在更大的意义上,对任何给定的外部命令执行相同的操作)

Start robocopy -args "$source $destination $fileLIst $robocopyOptions"
或者
robocopy $source $destination $fileLIst $robocopyOptions.split(' ')

Use the arrays, Luke.使用数组,卢克。 If you specify an array of values, PowerShell will automatically expand them into separate parameters.如果您指定一组值,PowerShell 会自动将它们扩展为单独的参数。 In my experience, this is the most reliable method.根据我的经验,这是最可靠的方法。 And it doesn't require you to mess with the Start-Process cmdlet, which is in my opinion is overkill for such tasks.而且它不需要您弄乱Start-Process cmdlet,在我看来,这对于此类任务来说太过分了。

This trick is from the best article I've seen on the PowerShell behavior towards external executables: PowerShell and external commands done right .这个技巧来自我见过的关于 PowerShell 对外部可执行文件的行为的最好的文章: PowerShell 和外部命令正确完成

Example:例子:

$source = 'C:\hold\first test'
$destination = 'C:\hold\second test'
$robocopyOptions = @('/NJH', '/NJS')
$fileList = 'test.txt'

$CmdLine = @($source, $destination, $fileList) + $robocopyOptions
& 'robocopy.exe' $CmdLine

You can't use a string to pass options in that way because when you write您不能使用字符串以这种方式传递选项,因为当您编写

robocopy $source $destination $fileList $robocopyOptions

PowerShell will evaluate the last variable ( $robocopyOptions ) as a single string and it will quote it. PowerShell 会将最后一个变量 ( $robocopyOptions ) 评估为单个字符串,并将其引用。 This means robocopy will get "/NJH /NHS" (single string, quoted) on its command line.这意味着 robocopy 将在其命令行上获得"/NJH /NHS" (单字符串,带引号)。 (Obviously not the intent.) (显然不是意图。)

For details on how to work around these kinds of issues, see here:有关如何解决此类问题的详细信息,请参见此处:

http://windowsitpro.com/powershell/running-executables-powershell http://windowsitpro.com/powershell/running-executables-powershell

The article includes the following function:文章包含以下功能:

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
  }
}

This function will let you run an executable in the current console window and also let you build an array of string parameters to pass to it.这个函数可以让你在当前控制台窗口中运行一个可执行文件,还可以让你构建一个字符串参数数组来传递给它。

So in your case you could use this function something like this:所以在你的情况下,你可以像这样使用这个函数:

Start-Executable robocopy.exe $source,$destination,$fileList,$robocopyOptions

Putting the options in separate arguments worked for me.将选项放在单独的参数中对我有用。 Using Robocopy for copying excluding any CSV files.使用 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM