使用通配符的 MSBuild 递归复制程序

6

我正在创建一个MSBuild v4任务,需要调用Copy任务来递归地复制一些文件(在目标位置不扁平化目录结构)。

我已经想到了以下代码:

var copy = new Microsoft.Build.Tasks.Copy
{
    BuildEngine = this.BuildEngine,
    SourceFiles = new ITaskItem[] { new TaskItem(@"C:\source\**\*.foo") },
    DestinationFolder = new TaskItem(@"c:\dest\\")
};
copy.Execute();

但是我遇到一个错误:“无法将C:\ source \ ** \ * .foo复制到c:\ dest \ * - 路径中有非法字符”。 关于实用方法的在线帮助似乎不多,我已经想破了头。有什么建议吗? 谢谢, Jon

如果那个方法起作用了,我认为它会扁平化你的文件夹结构,这是你想要的吗? - Ben Robinson
不,我想要将 c:\source\a\b\c.foo 复制到 c:\dest\a\b\c.foo - 谢谢,我会更新问题。 - Jon Bates
如果您将 c:\dest\ 中的双 \ 删除,这会有帮助吗? - oberfreak
双重目标是%(RecursiveDir)的解析值,由复制任务看到,尽管我尝试了许多斜杠排列组合。 - Jon Bates
3个回答

15

看起来复制任务并不具有递归的内在理解;以下代码会导致每个文件级别都调用复制任务,并且这由MSBuild运行器处理。

<ItemGroup>
  <x Include="c:\source\**\*.foo" />
</ItemGroup>
<Copy SourceFiles="@(x)" DestinationFolder="c:\dest\%(RecursiveDir)" />

然而,由于复制任务似乎将SourceFiles和DestinationFiles视为关联数组(每个类型为ITaskItem []),因此我们只需进行递归下降并手动构建这两个数组,然后执行即可。


2
问题在于,当你用XML编写相同的内容时,你不能直接将带通配符的路径传递给SourceFiles属性。你需要创建一个ItemGroup,然后将其传递给你的任务。
据我所知,是ItemGroup执行通配符操作,因此在C#中,您需要手动创建包含要复制的完整项目列表的ITaskItem数组。
如果可以的话,请创建一个ItemGroup,将其传递给您的任务,然后再将其传递给Copy

是ItemGroup(或至少是MSBuild)进行了扩展,这导致复制任务针对每个目录被调用一次。 - Jon Bates

1

你可以简单地使用MSBuild的Copy任务来完成。你不需要为此编写新的任务。

<Copy SourceFiles="@(SourceFiles)"
      DestinationFiles="$(DestinationFolder)\%(RecursiveDir)%(Filename)%(Extension)"
      ContinueOnError="false"/>

检查所有可用的MSBuild元数据


我们正在创建自己的C#任务,并希望在其中使用复制功能。看起来似乎不可能,但由于SO安全限制,我需要再等5个小时才能回答自己的问题。 - Jon Bates

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接