Powershell с Robocopy (или как # $ (*&передать аргументы правильно?)

Я пытаюсь написать сценарий, который использует robocopy. Если бы я просто делал это вручную, моя команда была бы:

robocopy c:holdtest1 c:holdtest2 тест.txt /NJH / NJS

но, когда я делаю это из powershell, например:

$source = "C:holdfirst test"
$destination = "C:holdsecond 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:holdfirst test
     Dest - C:holdsecond 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 параметры команды (и, в более широком смысле, сделайте то же самое для любой данной внешней команды)

3 ответов


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

эта функция позволит вам запустить исполняемый файл в текущем окне консоли, а также создать массив строковых параметров для его передачи.

поэтому в вашем случае вы можете использовать эту функцию примерно так:

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

используй массивы, Люк. Если указать массив значений, PowerShell автоматически развернет их в отдельные параметры. По моему опыту, это самый надежный способ. И это не требует от вас возиться с Start-Process командлет, который, на мой взгляд, является излишним для таких задач.

этот трюк из лучшей статьи, которую я видел в поведении PowerShell по отношению к внешним исполняемым файлам:PowerShell и внешние команды сделал право.

пример:

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

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