Compartilhar via


How To: Concatenate files using MSBuild tasks

This came across the internal MSBuild discussion alias this week:

How can I concatenate a bunch of individual files into a single file during my build process? It looks like the ReadLinesFromFile and WriteLinesToFile tasks will do what I want, but I can't figure out what kind of batching operators to use.

Dan provided an elegant answer. The first step is to create an ItemGroup with the files you want to concatenate:

<ItemGroup>   <InFiles Include="1.in;2.in"/></ItemGroup>

Then create a target to do the concatenation:

<Target Name="ConcatenateFiles">   <ReadLinesFromFile File="%(InFiles.Identity)">      <Output TaskParameter="Lines" ItemName="lines"/>   </ReadLinesFromFile>   <WriteLinesToFile File="test.out" Lines="@(Lines)" Overwrite="false" /></Target>

The first task, ReadLinesFromFiles, goes through each file in the InFiles list and adds their lines to a new list called Lines. To ensure that each file is done in a loop (batched), the .Identity item metadata is tacked on. The lines that are read in are added to a new property called Lines, which is created by using the Output element. Then WriteLinesToFile takes the generated list and spits them out to a file.

Pretty nifty!

[ Author: Neil Enns ]

Comments

  • Anonymous
    September 29, 2005
    Maybe I'm old-fashioned, but I can't help but think that the old:

    cat a b c > d

    is more elegant and easier to understand. It can easily be extended further, using bash script, easily inserted in a Makefile:

    cat $(find -iname *.cs | sort) > d

    This modern obsession with XML is fine for things that are wrapped up in a UI, but for something that needs programmer thought, you need (at some level) a programming language.

  • Anonymous
    September 29, 2005
    That's a fair point. We've actually often wished we had some sort of more straight forward programmability in MSBuild, directly embedded in the project file, for this kind of thing.

    There are other ways of achieving the above. As you mention, cat works, and you can involve it by from the <Exec> task.

    Another option, if you do this often, would be to write a task called <Cocnatenate> that takes the list of files and the output file name. It would certainly look nicer in the XML!

    The ReadLinesFromFiles and WriteLinesToFile tasks were never meant to be used this way, but I thought it was pretty cool that you could combine stuff in MSBuild in a way it was never intended to be used. Even though it's not a proper programming language, I'm always amazed at what you can do with our existing constructs.

    Neil

  • Anonymous
    December 15, 2006
    <a href="http://forddor.ifastnet.com/">Ford</a>">http://forddor.ifastnet.com/">Ford</a> or [url=http://forddor.ifastnet.com/]Ford[/url] or http://forddor.ifastnet.com/

  • Anonymous
    July 28, 2008
    How can i reset the taskparameter "Lines" if i want to read and write from and to another file? I have some problems if i try to write to a file in a new target, then i write the input from the earlier ReadFromFile job..

  • Anonymous
    August 18, 2008
    Just a note - this method strips out tab characters and blank lines

  • Anonymous
    August 28, 2008
    The comment has been removed

  • Anonymous
    September 02, 2008
    Hi how can I specify duplicate files in the InFiles Item and have them read in? i.e. <InFiles Include="1.in;2.in;1.in"/> Cheers! Neil

  • Anonymous
    February 10, 2009
    You can conatenate files like this: <ItemGroup>        <TextFiles Include="*.txt" Exclude="final.txt"/> </ItemGroup> <Exec Command="echo y| type %(TextFiles.Identity) >> final.txt"/>

  • Anonymous
    October 19, 2009
    >> <Exec Command="echo y| type %(TextFiles.Identity) >> final.txt"/> This unfortanately doesn't work if the files are UTF encoded with a BOM (Byte-order mark) since it will add the BOM at each seam.

  • Anonymous
    April 30, 2015
    This method trims heading spaces and tabs. So, this isn't actual files concatenation.