使用过滤器时,powershell copy-item不会复制

时间:2017-12-29 18:11:57

标签: windows powershell copy-item

我正在尝试使用copy-item复制文件。具体来说,我想将文件夹或其子文件夹中具有特定扩展名的文件复制到另一个位置,并保留子文件夹层次结构。我尝试使用-filter-include来指定文件扩展名,但不会复制任何文件。

我的源和目标路径存储在变量$packageSourcePath$objPath中。调用后,$packageSourcePath将类似于以下".\src\projects\Project1\PackageFiles",而$objPath将与以下".\bld\Project1\obj"类似。

我尝试使用的命令是:

Copy-Item -Path $packageSourcePath\* -Filter *.resw -Destination $objPath -Recurse

我也尝试过各种变体,例如从路径中取消*,或使用-Include而不是-Filter。什么都行不通。如果我省略-Filter参数,则文件会复制,但所有文件都会被复制。我只想要具有特定扩展名的文件。

2 个答案:

答案 0 :(得分:0)

这应该这样做(显然这可以在一行中完成;我已经为变量赋值,只是为了让它可读/不言自明):

[string]$filter = '*.resw'
[string]$source = Join-Path -Path $packageSourcePath -ChildPath '*'
[string]$target = $objPath
$source | Convert-Path | Copy-Item -Filter $filter -Recurse -Destination $target -Container #-Force

注意:

  • 我们将星号附加到源路径以确保我们将源文件夹的内容复制到目标,而不将源的根文件夹复制到目标(即我们将c:\temp\from复制到{{ 1}},我们不希望c:\temp\to(除非它是c:\temp\to\from的副本))。
  • 我们使用c:\temp\from\from cmdlet附加此星号,以确保在路径中插入相应的斜杠。
  • 我们在源上执行Join-Path以将星号解析为子文件夹/文件名...由于某种原因Convert-Path不能很好地处理这些星号。注意:copy-item可能会返回一系列路径;即如果源文件夹下直接有多个文件/子文件夹。 Convert-PathGet-Item同样适用于此;我更喜欢Resolve-Path,因为它返回一个简单的字符串数组,而不是更复杂的类型;但是使用任何一个都没有强烈的争论。
  • 我们将这些源路径传递给Convert-Path命令,以便它可以应用于Copy-Item返回的每个路径。
  • 我们包含Convert-Path表示我们对复制路径的子文件夹中的任何内容感兴趣。
  • 我们包含-Recurse参数,表示我们希望在复制时保留任何文件夹结构。严格来说这不是必需的,因为这个开关默认为true(即我们应该指定我们是否不想要这种行为:-Container;但我想清楚我故意想要保留目录结构,而不是假设我可能没有想到这一点。这里有更好的解释:https://stackoverflow.com/a/21798660/361842
  • 您可以选择包含-Container:$false;这意味着如果目标中已经存在同名项目,我们会覆盖它而不是出错。

相关文档:

更新2018-01-03

根据评论,此解决方案应确保只复制您想要的项目,并且预先存在的目录不应导致问题。

-Force

此解决方案使用2个步骤;可能有更好的选择,但由于此cmdlet中的特性/ bug以上是可靠的选项。

答案 1 :(得分:0)

我放弃了Copy-Item。 JohnLBevan的答案实际上没有按照我想要的那样做,因为源根目录中的所有文件都被复制,即使它们与过滤器不匹配。我尝试过使用Convert-Path | Select-String | Copy-Item但仍然复制了源根目录中的所有文件。

在不同背景下的联系人提供了一些建议:

1)

  

Get-ChildItem -Force -Recurse -ErrorAction Ignore -Path $ packageSourcePath -Filter * .resw | %{
      $ src = $ _。FullName
      $ dst = Join-Path $ objPath $ src.SubString($ packageSourcePath.Length)
      echo“copy”“$ src”“”“$ dst”“”
  }

我认为这有点难以理解,因此对于下一个人(可能是像我这样的另一个PS新手)来说,从现在起一年后就难以维持。 (“为什么这里需要-ErrorAction参数?Substring()方法的行为是什么,为什么我不能使用Get-Help找到它?”

在重新熟悉attrib并检查xcopy开关的效果之后,这个建议更加清晰:

2)

  

cd $ packageSourcePath
  attrib -a / s
  attrib + a * .resw / s
  xcopy / eidlm $ packageSourcePath $ objPath

但是如果我们要使用xcopy,我们不需要调用attrib:

  

xcopy $ packageSourcePath * .resw $ objPath / s / i> $空

我的方案唯一的问题是,如果找不到匹配的文件,xcopy会发出错误。我的脚本用于VSTS构建任务,xcopy错误导致构建任务失败。 (出于这个原因,我猜这个建议2也不适用于我。)

所以,我选择了这个:

   # In PS version 5.1, nothing gets copied using Copy-Item $packageSourcePath\* -Filter *.resw ...  
   # so resorting to using xcopy, which mostly works. The one issue is that xcopy will output an  
   # error if no matching file is found, so using GCI first to test for a matching file.  
   if ($(Get-ChildItem $packageSourcePath\*.resw -Recurse).count -gt 0) {
       xcopy $packageSourcePath\*.resw $objPath /s /i > $null
   }

添加使用GCI的条件以在调用xcopy之前检查是否存在匹配文件,从而避免任何错误。

我仍然惊讶于Copy-Item -Filter -Recurse不起作用。