【问题标题】:Recursively copied folders in MSBuild are incorrectly copied into one folderMSBuild 中递归复制的文件夹被错误地复制到一个文件夹中
【发布时间】:2016-02-10 14:32:07
【问题描述】:

我正在编写一个 MSBuild 目标/xml 配置文件。

假设我的项目源文件夹中有两个要复制的文件夹。我只想复制这些文件夹(及其内容),而忽略其他文件夹。

下面的规范是复制正确的文件,但是它们都只是转储到一个文件夹中。两个*文件夹(bin 和 obj)丢失,它们的内容只是合并到一个文件夹中。

我想基本上将这两个文件夹复制到新的*文件夹中,就像它们及其内容一样。

脚本

<Target Name="Package" DependsOnTargets="Build">
    <Message Text="Copying."></Message>
    <ItemGroup>
        <PackagedFiles Include="$(PipelineFolder)MyFolder\bin\**;
                                $(PipelineFolder)MyFolder\obj\**" />
    </ItemGroup>

    <MakeDir Directories="$(PipelineFolder)CopiedFolder" />
    <Copy SourceFiles="@(PackagedFiles)" DestinationFolder="$(PipelineFolder)CopiedFolder\%(RecursiveDir)%(Filename)%(Extension)" />

</Target>

仅复制*文件夹的最简单方法是什么,我猜 PackagedFiles 中的通配符指向这些文件夹中的所有内容。我不能从工作目录上方的文件夹中执行此操作,因为我将复制所有其他文件夹(不仅仅是我想要的文件夹,bin 和 obj)。

谢谢。

【问题讨论】:

    标签: .net msbuild target msbuild-target


    【解决方案1】:

    您可以为此使用批处理。第一个目标定义要包含的文件夹,第二个目标首先使用 use DependsOnTargets 属性定义这些文件夹。 Outputs 属性告诉MSBuild 对该目标使用批处理。

    <Project DefaultTargets="CopyPackageFolders" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
    
    <Target Name="DefinePackageFolders">
        <ItemGroup>
            <PackageFolders Include="bin"/>
            <PackageFolders Include="obj"/>
        </ItemGroup>
    </Target>
    
    <Target Name="CopyPackageFolders" DependsOnTargets="DefinePackageFolders" Outputs="%(PackageFolders.Identity)">
        <Message Text="Copying %(PackageFolders.Identity)" />
        <PropertyGroup>
            <TargetSubFolder>%(PackageFolders.Identity)</TargetSubFolder>
        </PropertyGroup>
        <ItemGroup>
            <Files Include="$(PipelineFolder)MyFolder\%(PackageFolders.Identity)\**" />
        </ItemGroup>
        <MakeDir Directories="$(PipelineFolder)CopiedFolder\%(PackageFolders.Identity)" />
        <Copy SourceFiles="@(Files)" DestinationFiles="$(PipelineFolder)CopiedFolder\$(TargetSubFolder)\%(RecursiveDir)%(Filename)%(Extension)" />
    </Target>
    
    </Project>
    

    注意:您必须将%(PackageFolders.Identity) 包装到一个单独的属性中,因为您不能在DestinationFiles 属性中使用两个不同的项目组。

    假设您有以下输入数据:

    C:\PipelineFolder\MyFolder\bin\bin.txt
    C:\PipelineFolder\MyFolder\obj\obj.txt
    

    假设提供的脚本位于C:\test.proj,那么您将使用给定的PipelineFolder 属性调用该脚本。

    C:\> msbuild test.proj /p:PipelineFolder=C:\PipelineFolder\
    

    生成的文件集将是:

    C:\PipelineFolder\CopiedFolder\bin\bin.txt
    C:\PipelineFolder\CopiedFolder\obj\obj.txt
    

    【讨论】:

    • 感谢您的回答!
    • 对不起,我才刚开始做这件事,我不得不搁置这个项目。这不是很有效,因为它仍然只是将所有匹配的文件转储到一个目录中,所以我现在没有将其标记为答案。在单独的目标中拥有“DefinePackageFolders”和“CopyPackageFolders”是否重要?
    • 它有点接近工作,但它仍然将所有文件放在我的一个嵌套文件夹中(第二个“obj”文件夹)
    • @dahui 目标的分离是设计使然。一个目标定义要分析的文件夹,另一个目标将为每个定义的文件夹调用。
    • @dahui 我添加了一组输入和输出数据的示例。也许您可以澄清该输出到底有什么问题。