Reputation: 2166
I am writing an MSBuild target/xml configuration file.
Let's say I have two folders in my project source folder which I want to copy over. I want to copy over just these folders (and their contents), and ignore the other folders.
The specification below is copying the correct files, however they are all just dumped into one folder. The two top level folders (bin and obj) are lost, and their contents are just combined into one folder.
I want to basically copy the two folders into the new top level folder, exactly as they and their contents are.
Script
<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>
What is the easiest way to copy just the top level folders, I guess the wildcard in the PackagedFiles are pointing to everything within these folders. I can't do this from the folder above the working directory as then I will copy all the other folders (not just the ones I want, bin and obj).
Thanks.
Upvotes: 0
Views: 274
Reputation: 41
You can use batching for that. The first target defines the folders to include and the second target first defines those folders with the use DependsOnTargets
attribute. The Outputs
attribute tells MSBuild
to use batching for that target.
<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>
Note: You have to wrap %(PackageFolders.Identity)
into a separate property because you can not use two different itemgroups in the DestinationFiles
attribute.
Lets say you have the following input data:
C:\PipelineFolder\MyFolder\bin\bin.txt
C:\PipelineFolder\MyFolder\obj\obj.txt
Let's assume the provided script is located in C:\test.proj
Then you would call the script with a given PipelineFolder
property.
C:\> msbuild test.proj /p:PipelineFolder=C:\PipelineFolder\
The resulting file set would be:
C:\PipelineFolder\CopiedFolder\bin\bin.txt
C:\PipelineFolder\CopiedFolder\obj\obj.txt
Upvotes: 1