在 Powershell 5 中使用 Robocopy
Using Robocopy with Powershell 5
我将我的开发机器升级到 Powershell 5,现在在 PS2 中工作的代码在 PS5 中不工作。
我的代码使用 Robocopy 将文件从 svn 签出目录复制到工作目录。它还用于清理工作目录。
原始代码如下所示:
$what = @("""/copy:DAT""","""/E""","/XD .svn","/XD Debug","/XF .pdb")
$options = @("""/R:4""","""/W:5""","""/TS""","""/NS""","""/Tee""","""/NP""")
if ($file) {
$cmdArgs = @("""$src""", """$dest""", """$file""", $what, $options)
}else
{
$cmdArgs = @("""$src""", """$dest""", $what, $options)
}
robocopy $cmdArgs
当命令使用 powershell 5 运行时,我得到
ERROR : Invalid Parameter #3 : "/copy:DAT /E /XD .svn /XD Debug /XF
.pdb"
我明白发生了什么,它将参数视为一个单独的命令而不是单独的参数。
我试过单双引号,我试过单引号,但我仍然得到相同的结果。
如果我将选项硬编码到执行行,
robocopy $cmdArgs /COPY:DAT /E /XD .svn /XD Debug /XF .pdb /R:4 /W:5
/TS /NS /Tee /NP
那么命令就可以工作了,所以我现在有一个解决方法,但仍然宁愿使用原始的参数化结构。
我需要做什么才能让 PS5 正常工作?谢谢。
编辑:使用 Windows 10 和 PS5,我收到以下错误:
错误:无效参数 #5:“/XD .svn”
$what = @("""/PURGE""","""/E""","/XD .svn","/XD Debug","/XF .pdb")
$options = @("""/R:4""","""/W:5""","""/TS""","""/NS""","""/Tee""","""/NP""")
$cmdArgs = @("""$srcBase""","""$targetPath"""; $what)
对于'/XD .svn',我尝试用三引号、单引号、转义引号等将其括起来。但是,没有成功。
您正在构造一个锯齿状数组。您可以通过在 运行 您包含的代码
之后查看 $cmdargs 的结果来验证这一点
""
""
"/copy:DAT"
"/E"
/XD .svn
/XD Debug
/XF .pdb
"/R:4"
"/W:5"
"/TS"
"/NS"
"/Tee"
"/NP"
这看起来不错,但如果您只访问第三个元素 $cmdArgs[2],您会发现它包含了 $what 数组的全部内容
"/copy:DAT"
"/E"
/XD .svn
/XD Debug
/XF .pdb
作为一种快速而肮脏的解决方法,请尝试以下操作:
$what = @("""/copy:DAT""","""/E""","/XD .svn","/XD Debug","/XF .pdb")
$options = @("""/R:4""","""/W:5""","""/TS""","""/NS""","""/Tee""","""/NP""")
if ($file) {
$cmdArgs = @("""$src""", """$dest""", """$file""")
$cmdArgs += $what
$cmdArgs += $options
}else
{
$cmdArgs = @("""$src""", """$dest""")
$cmdArgs += $what
$cmdArgs += $options
}
robocopy $cmdArgs
编辑:
上面的轻微编辑,和
More on Jagged vs Multidimensional vs standard arrays here。看向底部。本质上,您构建数组的方式被解释为 @(0,1,(0,1,2,3,4),(0,1,2,3,4,5))
哇!多么痛苦,但我有一个解决方案。
我不得不使用字符串拆分方法并按空格拆分。我不得不放弃数组并创建一个字符串。
$cmdArgs = @("""$srcBase""", """$targetPath""") #still required for quoted paths
$what = "/PURGE /E /XD .svn /XD DEBUG /XF .pdb"
$options = "/R:4 /W:5 /TS /NS /Tee /NP"
robocopy $cmdArgs $what.split(' ') $options.split(' ')
PS 2.0 和更高版本之间的一些更改破坏了我的代码,但这似乎修复了它。希望这有助于将其他人从痛苦的日子中拯救出来。 :)
编辑:考虑到这一点后,我认为这是 PS 和 Robocopy 之间的问题,其中具有值的参数无法正确评估。令我感到羞耻的是,我试了很多次才尝试一个简单的字符串作为参数。
太多令人难以置信的报价!除了您的源路径和目标路径之外,您真的根本不需要它们。我发现最好的方法是创建一个格式化的字符串表达式然后执行它。
$what = "/copy:DAT /E /XD .svn /XD Debug /XF .pdb"
$options = "/R:4 /W:5 /TS /NS /Tee /NP"
$source = "C:\DataSource"
$destination = "D:\DataDestination"
$expression = [string]::Format('ROBOCOPY "{0}" "{1}" {2} {3}', $source,$Destination,$what,$options)
$rc = Invoke-Expression $expression
$rc = $LASTEXITCODE;
Switch ($rc)
{
0 {$msg = 'No files were copied. No failure was encountered. No files were mismatched.'}
1 {$msg = 'All files were copied successfully.'}
2 {$msg = 'There are some additional files in the destination directory that are not present in the source directory. No files were copied.'}
3 {$msg = 'Some files were copied. Additional files were present. No failure was encountered.'}
5 {$msg = 'Some files were copied. Some files were mismatched. No failure was encountered.'}
6 {$msg = 'Additional files and mismatched files exist. No files were copied and no failures were encountered. This means that the files already exist in the destination directory.'}
7 {$msg = 'Files were copied, a file mismatch was present, and additional files were present.'}
8 {$msg = 'Several files did not copy.'}
default {$msg = 'Robocopy failed with an error'}
}
$msg
If($rc -ge 8) {Throw}
我将我的开发机器升级到 Powershell 5,现在在 PS2 中工作的代码在 PS5 中不工作。
我的代码使用 Robocopy 将文件从 svn 签出目录复制到工作目录。它还用于清理工作目录。
原始代码如下所示:
$what = @("""/copy:DAT""","""/E""","/XD .svn","/XD Debug","/XF .pdb")
$options = @("""/R:4""","""/W:5""","""/TS""","""/NS""","""/Tee""","""/NP""")
if ($file) {
$cmdArgs = @("""$src""", """$dest""", """$file""", $what, $options)
}else
{
$cmdArgs = @("""$src""", """$dest""", $what, $options)
}
robocopy $cmdArgs
当命令使用 powershell 5 运行时,我得到
ERROR : Invalid Parameter #3 : "/copy:DAT /E /XD .svn /XD Debug /XF .pdb"
我明白发生了什么,它将参数视为一个单独的命令而不是单独的参数。 我试过单双引号,我试过单引号,但我仍然得到相同的结果。
如果我将选项硬编码到执行行,
robocopy $cmdArgs /COPY:DAT /E /XD .svn /XD Debug /XF .pdb /R:4 /W:5 /TS /NS /Tee /NP
那么命令就可以工作了,所以我现在有一个解决方法,但仍然宁愿使用原始的参数化结构。
我需要做什么才能让 PS5 正常工作?谢谢。
编辑:使用 Windows 10 和 PS5,我收到以下错误: 错误:无效参数 #5:“/XD .svn”
$what = @("""/PURGE""","""/E""","/XD .svn","/XD Debug","/XF .pdb")
$options = @("""/R:4""","""/W:5""","""/TS""","""/NS""","""/Tee""","""/NP""")
$cmdArgs = @("""$srcBase""","""$targetPath"""; $what)
对于'/XD .svn',我尝试用三引号、单引号、转义引号等将其括起来。但是,没有成功。
您正在构造一个锯齿状数组。您可以通过在 运行 您包含的代码
之后查看 $cmdargs 的结果来验证这一点""
""
"/copy:DAT"
"/E"
/XD .svn
/XD Debug
/XF .pdb
"/R:4"
"/W:5"
"/TS"
"/NS"
"/Tee"
"/NP"
这看起来不错,但如果您只访问第三个元素 $cmdArgs[2],您会发现它包含了 $what 数组的全部内容
"/copy:DAT"
"/E"
/XD .svn
/XD Debug
/XF .pdb
作为一种快速而肮脏的解决方法,请尝试以下操作:
$what = @("""/copy:DAT""","""/E""","/XD .svn","/XD Debug","/XF .pdb")
$options = @("""/R:4""","""/W:5""","""/TS""","""/NS""","""/Tee""","""/NP""")
if ($file) {
$cmdArgs = @("""$src""", """$dest""", """$file""")
$cmdArgs += $what
$cmdArgs += $options
}else
{
$cmdArgs = @("""$src""", """$dest""")
$cmdArgs += $what
$cmdArgs += $options
}
robocopy $cmdArgs
编辑: 上面的轻微编辑,和 More on Jagged vs Multidimensional vs standard arrays here。看向底部。本质上,您构建数组的方式被解释为 @(0,1,(0,1,2,3,4),(0,1,2,3,4,5))
哇!多么痛苦,但我有一个解决方案。 我不得不使用字符串拆分方法并按空格拆分。我不得不放弃数组并创建一个字符串。
$cmdArgs = @("""$srcBase""", """$targetPath""") #still required for quoted paths
$what = "/PURGE /E /XD .svn /XD DEBUG /XF .pdb"
$options = "/R:4 /W:5 /TS /NS /Tee /NP"
robocopy $cmdArgs $what.split(' ') $options.split(' ')
PS 2.0 和更高版本之间的一些更改破坏了我的代码,但这似乎修复了它。希望这有助于将其他人从痛苦的日子中拯救出来。 :)
编辑:考虑到这一点后,我认为这是 PS 和 Robocopy 之间的问题,其中具有值的参数无法正确评估。令我感到羞耻的是,我试了很多次才尝试一个简单的字符串作为参数。
太多令人难以置信的报价!除了您的源路径和目标路径之外,您真的根本不需要它们。我发现最好的方法是创建一个格式化的字符串表达式然后执行它。
$what = "/copy:DAT /E /XD .svn /XD Debug /XF .pdb"
$options = "/R:4 /W:5 /TS /NS /Tee /NP"
$source = "C:\DataSource"
$destination = "D:\DataDestination"
$expression = [string]::Format('ROBOCOPY "{0}" "{1}" {2} {3}', $source,$Destination,$what,$options)
$rc = Invoke-Expression $expression
$rc = $LASTEXITCODE;
Switch ($rc)
{
0 {$msg = 'No files were copied. No failure was encountered. No files were mismatched.'}
1 {$msg = 'All files were copied successfully.'}
2 {$msg = 'There are some additional files in the destination directory that are not present in the source directory. No files were copied.'}
3 {$msg = 'Some files were copied. Additional files were present. No failure was encountered.'}
5 {$msg = 'Some files were copied. Some files were mismatched. No failure was encountered.'}
6 {$msg = 'Additional files and mismatched files exist. No files were copied and no failures were encountered. This means that the files already exist in the destination directory.'}
7 {$msg = 'Files were copied, a file mismatch was present, and additional files were present.'}
8 {$msg = 'Several files did not copy.'}
default {$msg = 'Robocopy failed with an error'}
}
$msg
If($rc -ge 8) {Throw}