Compartilhar via


How To: Recursively Copy Files Using the 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 ]

Comments

  • Anonymous
    December 20, 2005
    This is very useful. Is there a way to skip files with a certain extension?

  • Anonymous
    March 01, 2006
    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?

  • Anonymous
    March 02, 2006
    In MSBuild, to copy a part of subtree, resembling directory structure, you have to write small and simple task. ...

  • Anonymous
    April 17, 2006
    copy files using <a href="http://www.yaodownload.com/utilites/file-disk-management/filemonkey/">FileMonkey</a>">http://www.yaodownload.com/utilites/file-disk-management/filemonkey/">FileMonkey</a> , it's really good!


    http://www.yaodownload.com/utilites/file-disk-management/filemonkey/

  • Anonymous
    May 10, 2006
    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>' />


  • Anonymous
    June 14, 2006
    I'm really growing to like MSBuild, but some of it's syntax is just needlessly cryptic.&amp;nbsp; For example...

  • Anonymous
    September 19, 2006
    As part of my conversion to Asp.Net 2 I had decided to utilise Msbuild over Nant. In my Asp.net 1.1 build

  • Anonymous
    October 11, 2006
    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.

  • Anonymous
    October 12, 2006
    I've further determined that it fails with administrative shares such as \servere$ but not normal shares such as \serverbuildoutput

  • Anonymous
    October 31, 2006
    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.

  • Anonymous
    November 14, 2006
    I'm running into some weird problems.  Following is the file collection I am using: <!--File Collection-->  <ItemGroup>     <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)coremdsWinRel***.dll" />     <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)coreWinRel***.dll" />     <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)coreWinRel***.exe" />     <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)coreWinRel***.tlb" />     <SourceFiles Include="$(SOURCECODE_ROOT)$(FolderName)coreWinRel***.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!

  • Anonymous
    November 16, 2006
    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.

  • Anonymous
    January 03, 2007
    We got a great question at msbuild@microsoft.com last week: What is the preferred method to retrieve

  • Anonymous
    August 16, 2007
    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_coreMapDataServerWinRel***.dll;                          $(SOURCECODE_ROOT)$(FolderName)fvw_coreWinRel***.dll;                          $(SOURCECODE_ROOT)$(FolderName)fvw_coreWinRel***.exe;                          $(SOURCECODE_ROOT)$(FolderName)fvw_coreWinRel***.tlb;                          $(SOURCECODE_ROOT)$(FolderName)fvw_coreWinRel***.ocx">        <Output TaskParameter="Include" ItemName="SourceFiles" />     </CreateItem>

  • Anonymous
    August 23, 2007
    I have this code: <ItemGroup> <ReleaseFiles Include="$(FuentesDir)PruebabinRelease*.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?

  • Anonymous
    October 10, 2007
    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 releasebin folder.  In affect I have this structure: Original_Product_DirectoryversionFile.Txt This single fiel I want copied to the following folder structure: New_Product_DirectorySub_Product_AReleaseBin New_Product_DirectorySub_Product_BReleaseBin New_Product_DirectorySub_Product_CReleaseBin New_Product_DirectorySub_Product_DReleaseBin ... .. . 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.

  • Anonymous
    December 11, 2007
    I got today hysterical message from a good friend that implementing in his company automatic build with

  • Anonymous
    February 17, 2008
    The comment has been removed

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

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

  • Anonymous
    November 02, 2008
    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>

  • Anonymous
    December 16, 2008
    PingBack from http://adallow.wordpress.com/2008/12/17/msbuild-copying-files/

  • Anonymous
    January 15, 2009
    The comment has been removed

  • Anonymous
    February 20, 2009
    I'm trying to copy from "%INSDIR%add_distSQL Server" to "ISDIRmediadefaultdiskmagesDisk1". 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%mediadefaultdisk imagesDisk1"        />    </Target>

  • Anonymous
    October 12, 2009
    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

  • Anonymous
    November 30, 2009
    this article is rubbish, how is a person that has never used MSBuild before supposed to know that  <Copy SourceFiles="@(Compile)" DestinationFolder="c:foocopy%(RecursiveDir)"></Copy> is supposed to be wrapped inside a task element? how about providing a full working template instead of assuming everybody knows how to impliment this?

  • Anonymous
    March 05, 2010
    Hi Team, Thanks this saved me some time. Could you guys please fix the msdn documentation at http://msdn.microsoft.com/en-us/library/3e54c37h%28v=VS.90%29.aspx so that it works as the above code does. Could you also work in an "Exclude" example that is more than trivial. Otherwise very useful. Cheers Simon

  • Anonymous
    July 06, 2010
    Something totally different. I want to create a parameterized target with MSBuild. Is this possible? If not, are there plans to implement this in a later version?

  • Anonymous
    February 12, 2011
    The Bounce (github.com/.../bounce) build framework makes recursive directory copy pretty straightforward: github.com/.../CopyTask

  • Anonymous
    April 07, 2011
    What if I want to copy a folder, together with its contents?  That is irrecpective of their different extensions.