I got a directory I want to copy to a number of locations.
Say I have
I want to copy it to
You really are best off doing this yourself as a learning exercise, rather than treating MSBUILD as a magic box. This article from Patrick Smacchia gives you most of the techniques involved.
The concept that you should be interested in is known as Batching.
I've covered this exact scenario on my blog at http://www.sedodream.com/PermaLink,guid,5f1e0445-ce3d-4052-ba80-42fd19512d42.aspx
Here is the text of that blog entry, you can download the mentioned files at the link above.
Today someone was telling me about a co-worker who was having issues with MSBuild. He told me that he was trying to copy a set of files to a set of different servers. But the issue was that he didn’t know how to achieve this without performing multiple Copy task invocations. I told him that he could achieve this using MSBuild Batching. Batching is a process of performing a task (or target) on a set of items (batches) at a time. A batch can also include a single item. So in this scenario we need to perform the copy one time for each server that he wanted to deploy to. I’ve created a simple msbuild file which demonstrates this in two different ways. The first way uses task batching, which can bee seen in the Test target. And the other uses Target batching which can be seen in the DoItCore target. I've also created a clean target, which has nothing to do with batching.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Test">
<ItemGroup>
<SourceFiles Include="*.txt"/>
<Dest Include="One;Two;Three;Four;Five"/>
</ItemGroup>
<Target Name="Test">
<Copy SourceFiles ="@(SourceFiles)" DestinationFolder="%(Dest.FullPath)"/>
<Message Text="Fullpath: %(Dest.FullPath)"/>
</Target>
<!-- These targets demonstrate target batching -->
<Target Name="DoIt" DependsOnTargets="DoItCore"/>
<Target Name="DoItCore" Inputs="@(SourceFiles)" Outputs="%(Dest.FullPath)">
<Copy SourceFiles="@(SourceFiles)" DestinationFolder="%(Dest.FullPath)"/>
</Target>
<!-- This will clean up the files -->
<Target Name="Clean">
<CreateItem Include="%(Dest.FullPath)\**\*">
<Output ItemName="FilesToDelete" TaskParameter="Include"/>
</CreateItem>
<Delete Files="@(FilesToDelete)"/>
</Target>
</Project>
Batching is an advanced topic of MSBuild, and is defintely neglected. I have to admit I’m guilty of not writing about it enough myself. There are some good batching resources, they are listed below.
Here are some other batching related blog entries that I've posted.
Thanks, Sayed Ibrahim Hashimi
My Book: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build
Have an itemgroup where you build up this list of destinations ("<Destination>abc</Destionation>..., etc). Then invoke the copy task with this list (@Destination).
I'm sure you'll find plenty of examples if you search for it. http://keithhill.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=cat%3dMSBuild
Here is an actual example that I put together that shows what you were looking for:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Test" ToolsVersion="3.5">
<!--Declare an ItemGroup that points to your file you want to copy.-->
<ItemGroup>
<ItemToCopy Include=".\Home.aspx" />
</ItemGroup>
<!--Declare an ItemGroup that points to your destination Locations-->
<ItemGroup>
<DestLocations Include=".\abc\home.aspx" />
<DestLocations Include=".\def\home.aspx" />
<DestLocations Include=".\ghi\home.aspx" />
</ItemGroup>
<Target Name="CopyFiles">
<!--Run the copy command to copy the item to your dest locations-->
<!--This is where the magic happens. The % sign before the DestLocations reference says to use
Batching. So Copy will be run for each unique FullPath MetaData in the DestLocations ItemGroup.-->
<Copy SourceFiles="@(ItemToCopy)" DestinationFolder="%(DestLocations.FullPath)" />
</Target>
</Project>