Welcome to MSDN Blogs Sign in | Join | Help

How To: Recursively Copy Files Using the <Copy> Task

Have you ever run into a situation where you had to recursively copy files from one folder into another as a part of your build process?  We certainly have run into it a few times, and I thought I'd share with you a neat trick that involves the use of metadata and the Copy task.

Before you can copy a set of files, you need to be able to recursively add those files to an item list. Here's how you do that when declaring items.

   <ItemGroup>
      <
Compile Include=".\**\*.cs" /
   
</ItemGroup>

The ** wildcard is used in item includes to indicate recursive includes.

So, once you have an item declared as such, you can rely on a piece of standard meta-data that goes with all items (i.e. RecursiveDir) to accomplish your recursive copy. The RecursiveDir metadata when used will return the evaluated value of the ** metadata for each item - and you can use that value to preserve the folder structure for each file when performing the copy. Here's how you invoke the <Copy> task using this piece of metadata to copy recursively.

   <Copy SourceFiles="@(Compile)" DestinationFolder="c:\foocopy\%(RecursiveDir)"></Copy>

Hope this helps! Let us know if these tips/tricks and how-tos are useful.

[ Author: Faisal Mohamood ]

Published Monday, November 07, 2005 10:58 PM by msbuild
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Tuesday, December 20, 2005 8:50 PM by Pablo

# re: How To: Recursively Copy Files Using the <Copy> Task

This is very useful. Is there a way to skip files with a certain extension?
Thursday, March 02, 2006 6:03 AM by Andrew Mayorov

# re: How To: Recursively Copy Files Using the &lt;Copy&gt; Task

Well, this is very good, but what should i do, if i have to copy only files with certain extensions and form certain subdirectories of one give subtree root. For example, in NAnt i do it like this:

<copy todir="sdfTestWeb/private">
<fileset basedir="${solution.path}/sdf.SPanel/private">
<include name="*.sdf"/>
<include name="*.aspx"/>
<include name="*.asmx"/>
<include name="*.inc"/>
<include name="web.config"/>
<include name="images/**/*.*"/>
<include name="scripts/**/*.*"/>
<include name="styles/**/*.*"/>
<include name="xml/**/*.*"/>
<include name="xsl/**/*.*"/>
<exclude name="**/*.vss"/>
</fileset>
</copy>

It copies all specified files resembling the directory structure. Only necessary files, as you can see. In fact, the subtree contains also a whole bunch of unneded files.

How could i do it with MSBuild?
Thursday, March 02, 2006 10:07 AM by devPort strikes back!

# Copy a subtree with MSBuild

Thursday, March 02, 2006 10:12 AM by devPort strikes back!

# Copy a subtree with MSBuild

In MSBuild, to copy a part of subtree, resembling directory structure, you have to write small and simple task. ...
Monday, April 17, 2006 9:36 PM by tom

# re: How To: Recursively Copy Files Using the &lt;Copy&gt; Task

Wednesday, May 10, 2006 11:44 AM by AndrewSeven

# re: How To: Recursively Copy Files Using the &lt;Copy&gt; Task

Did you ever just want a simple way to copy a folder from one place to annother without any fuss? Xcopy works pretty good.


<Exec Command='xcopy /E <from> <to>' />


Wednesday, June 14, 2006 11:59 AM by Eric Bowen's .NET Technology Blog

# MSBUILD: Why does Microsoft have to keep inventing new solutions to old problems?

I'm really growing to like MSBuild, but some of it's syntax is just needlessly cryptic.&amp;nbsp; For example...
Tuesday, September 19, 2006 12:58 PM by Eamonn's Blog

# MSBuild not very Nant User Friendly

As part of my conversion to Asp.Net 2 I had decided to utilise Msbuild over Nant. In my Asp.net 1.1 build
Wednesday, October 11, 2006 6:09 PM by Christopher Painter

# re: How To: Recursively Copy Files Using the <Copy> Task

I'm just learning msbuild ( mostly done NAnt in the past ) and I'm wondering why this doesn't work when the ItemGroup Include attribute points to a UNC path?

Basically my files get copied, but they are flattened into a single destination directory.   If I map the drive and change my Include attribute it works correctly.

Thursday, October 12, 2006 10:27 AM by Christopher Painter

# re: How To: Recursively Copy Files Using the <Copy> Task

I've further determined that it fails with administrative shares such as \\server\e$ but not normal shares such as \\server\buildoutput

Tuesday, October 31, 2006 1:55 PM by Matt Wright

# re: How To: Recursively Copy Files Using the <Copy> Task

Excellent Tip! Keep 'em coming. That's really sorted me out. I'm using the new web deployment http://weblogs.asp.net/scottgu/archive/2005/11/06/429723.aspx project which is great. Somehow though it copies all the .csproj files and everything into it's release directory??? Strange, I thought it would operate more like a "Publish" of the web site like in Visual Studio? Oh well.

Wednesday, November 15, 2006 7:50 AM by George

# re: How To: Recursively Copy Files Using the <Copy> Task

I'm running into some weird problems.  Following is the file collection I am using:

<!--File Collection-->

 <ItemGroup>

    <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)\core\mds\WinRel\**\*.dll" />

    <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)\core\WinRel\**\*.dll" />

    <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)\core\WinRel\**\*.exe" />

    <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)\core\WinRel\**\*.tlb" />

    <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)\core\WinRel\**\*.ocx" />

 </ItemGroup>

Here is the copy task I am using:

<Copy SourceFiles="@(SourceFiles)" DestinationFiles="@(SourceFiles->'$(EXECUTABLES_ROOT)$(FolderName)\$(BuildLevel)\%(RecursiveDir)%(Filename)%(Extension)')" />

This only _sometimes_ works.  For instance, today, the .exe didn't get copied nor did any of the subdirectories.  Does anyone see anything wrong with the above?  Thanks!

Thursday, November 16, 2006 5:29 PM by George

# re: How To: Recursively Copy Files Using the <Copy> Task

I was able to get the Copy tasks to work consistently by moving these tasks into a separate target.  Previously, I had:

<msbuild ... >

<copy ... >

<removedir ... >

<copy ... >

<msbuild ... >

When I move the copy/removedir/copy into a separate task it works fine every time.  Pretty weird.

Wednesday, January 03, 2007 5:25 PM by MSBuild Team Blog

# How To: Retrieve the AssemblyVersion using AssemblyInfoTask

We got a great question at msbuild@microsoft.com last week: What is the preferred method to retrieve

Thursday, August 16, 2007 10:00 AM by George

# re: How To: Recursively Copy Files Using the <Copy> Task

The reason the copy task seemed to sometimes work and not other is because I was bit by the ItemGroup being created as soon as the build script was loaded.  If some of the files didn't exist when the build script was loaded then they would not be copied.

The way around this, as probably everyone knew but me, is to use a CreateItem task and create the items dynamically:

<CreateItem Include="$(SOURCECODE_ROOT)$(FolderName)\fvw_core\MapDataServer\WinRel\**\*.dll;

                         $(SOURCECODE_ROOT)$(FolderName)\fvw_core\WinRel\**\*.dll;

                         $(SOURCECODE_ROOT)$(FolderName)\fvw_core\WinRel\**\*.exe;

                         $(SOURCECODE_ROOT)$(FolderName)\fvw_core\WinRel\**\*.tlb;

                         $(SOURCECODE_ROOT)$(FolderName)\fvw_core\WinRel\**\*.ocx">

       <Output TaskParameter="Include" ItemName="SourceFiles" />

    </CreateItem>

Thursday, August 23, 2007 9:03 AM by Patricio

# re: How To: Recursively Copy Files Using the <Copy> Task

I have this code:

<ItemGroup>

<ReleaseFiles Include="$(FuentesDir)\Prueba\bin\Release\*.dll"/>

</ItemGroup>

<Target Name = "build" >

<MSBuild Projects = "Prueba.sln" Properties = "Configuration=Release" />

<Copy SourceFiles="@(ReleaseFiles)" DestinationFolder="$(ReleaseDir)" />

</Target>

The copy dont work because at first @(ReleaseFiles) is empty.

Could somebody hep me?

Wednesday, October 10, 2007 6:00 PM by T L

# re: How To: Recursively Copy Files Using the <Copy> Task

I am trying to use MSBuild Copy function to copy a single text file (a version file)  that is created imediately upon build to several specific projects release\bin folder.  In affect I have this structure:

\Original_Product_Directory\versionFile.Txt

This single fiel I want copied to the following folder structure:

\New_Product_Directory\Sub_Product_A\Release\Bin\

\New_Product_Directory\Sub_Product_B\Release\Bin\

\New_Product_Directory\Sub_Product_C\Release\Bin\

\New_Product_Directory\Sub_Product_D\Release\Bin\

...

..

.

The Sub_Product _? folder can be one of many and may change over time so the task has to eb somewhat dynamic.  Please provide any suggestions or examples that would help.

Thanks.

Tuesday, December 11, 2007 6:27 PM by Maor David

# Copy WildCards With MSBuild

I got today hysterical message from a good friend that implementing in his company automatic build with

Sunday, February 17, 2008 11:53 PM by this.Reflect(); - Donn's Weblog

# Frustrated... Party of 1! MSBuild ... PLEASE JUST WORK!

Photo by: mistyeiz A couple of weeks ago I had one hell of a time with an MSBuild script. I felt like

Thursday, February 28, 2008 2:24 PM by Wout

# re: How To: Recursively Copy Files Using the <Copy> Task

Doesn't work for me, all files end up in the same dir. Shouldn't you copy using DestinationFiles and a transform?

Thursday, February 28, 2008 2:39 PM by Wout

# re: How To: Recursively Copy Files Using the <Copy> Task

Ah, didn't work because the folder was a UNC path. Looks like more people had that problem.

Sunday, November 02, 2008 5:23 PM by David

# re: How To: Recursively Copy Files Using the <Copy> Task

I found the code did not work:

<Copy SourceFiles="@(Compile)" DestinationFolder="c:\foocopy\%(RecursiveDir)"></Copy>

Correct version

<Copy SourceFiles="@(Compile)" DestinationFolder="c:\foocopy\%(RecursiveDir)%(Filename)%(Extension)"></Copy>

Wednesday, December 17, 2008 12:50 AM by MSBuild Copying Files &laquo; Alberts Tech Log

# MSBuild Copying Files &laquo; Alberts Tech Log

Thursday, January 15, 2009 9:40 AM by Patrick Martin

# re: How To: Recursively Copy Files Using the <Copy> Task

I found that this corrected code did not work for me:

<Copy SourceFiles="@(Compile)" DestinationFolder="c:\foocopy\%(RecursiveDir)%(Filename)%(Extension)"></Copy>

This code produced the following error in the build log:

...error MSB4094: <filelist> ...is an invalid value for the "DestinationFolder" parameter of the "Copy" task. Multiple items cannot be passed into a parameter of type "Microsoft.Build.Framework.ITaskItem".

Using Team Build 2008 the copy task needed to be changed as follows:

<Copy SourceFiles="@(Compile)" DestinationFiles="c:\foocopy\%(RecursiveDir)%(Filename)%(Extension)"></Copy>

Friday, February 20, 2009 12:38 PM by Mihir

# re: Trouble having Recursively Copy Files Using the <Copy> Task

I'm trying to copy from "%INSDIR%\add_dist\SQL Server" to "ISDIR\media\default\diskmages\Disk1". Also, SQL Server has another sub directory. I've tried following code in my batch file. I'm getting an error like : The syntax of the command is incorrect.

<ItemGroup>

       <MySourceFiles Include="%ISDIR%\add_dist\**\*.*"/>

   </ItemGroup>

   <Target Name="CopyFiles">

       <Copy

           SourceFiles="@(MySourceFiles)"

           DestinationFolder="%ISDIR%\media\default\disk images\Disk1"

       />

   </Target>

Monday, October 12, 2009 11:01 PM by Vishrut

# re: How To: Recursively Copy Files Using the <Copy> Task

Can any one suggest me how we can copy to multiple destination using a single target.Below is the syntax to do it for one location but I want to do it for multiple locations.

<Target Name="CopyFiles">

<Copy SourceFiles="@(MySourceFiles)"

DestinationFiles="@(MySourceFiles->'c:\MyDstnTree

\%(RecursiveDir)%(Filename)%(Extension)')"

/></Target>

It would be real good if someone can achieve the same using RoboCopy. Please help. I am in dire need of solution. You can mail me atvishrut24@gmail.com

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker