views:

1101

answers:

3

Let me preface by saying that I'm new to ant, and I'm using version 1.6.5 if it matters.

I have a file with a list of files that I want to concatenate. The relevant part of my first attempt was this:

<target name="for-each">
    <xmlproperty file="scripts.xml" collapseAttributes="true" />
    <echo message="testing for-each"/>
    <concat destfile="${out}" fixlastline="yes" eol="lf">
        <foreach list="${scripts.src}" target="loop" param="var" delimiter=","/>
    </concat>
</target>

<target name="loop">
    <echo message="File :: ${var}"/>
    <fileset file="${SRC_DIR}${var}" />
</target>

However, concat doesn't support the foreach element.

I don't simply want to cut and paste a fileset into the concat element because it's reused and may be changed in the original file often, so I want to programmaticly iterate over the script elements listed in my file instead.

What would the right syntax be or how would I accomplish this?

+4  A: 

I think your requirements are:

  • load the filelist from another xml file
  • concat this filelist together

If that's the case, there's no reason you should be making your own procedural loop. You can do something like:

scripts.xml

<scripts>
   <src>file1</src>
   <src>file2</src>
</scripts>

build.xml

<xmlproperty file="scripts.xml" collapseAttributes="true" />
<concat destfile="${out}" fixlastline="yes" eol="lf">
    <filelist files="${scripts.src}"/>
</concat>

is this the case?

Jweede
Hmm ... I hope it will be something simple like that, but according to http://ant.apache.org/manual/CoreTypes/filelist.html, files is a list of file names separated by whitespace, or by commas. So my scripts.xml file will have to have that list in a single attribute value somewhere or as a single comma separate child, right? I guess that I'm asking if I have more flexibility with fileset than it looks like a do or will I have to have an XML file that conforms to what filelist expects?
Keith Bentrup
A fileset is defined by exclusions mostly, and a filelist is defined by inclusions. If you have a short list of files, I would stick with the filelist. Otherwise, if you files follow a pattern or are likely to be numerous, make a careful fileset that selects the proper ones.
Jweede
I'm pretty sure if `<XMLProperty>` runs into: <List> <Item/> <Item/> </List>It will concatinate the values into one property ${List.Item}. This might be what you're looking for.
Jweede
+1, I'll try it and see what I can do, but you're definitely getting me closer to a solution. Thx.
Keith Bentrup
No prob. ANT can only do so much. For some of my larger ANT processes, I write modules in python to do the harder stuff, and launch it from ANT.
Jweede
A: 

Something like this might work (didn't try it)

<foreach param="file" list="${files}" target="concat_one_file" inheritall="true"/>

  <target name="concat_one_file">
    <do_concat source="${file}" destination="destination.txt"/>
  </target>


  <macrodef name="do_concat">
    <attribute name="source"/>
    <attribute name="destination"/>
    <sequential>
      <concat destfile="@{destination}" append="yes">
        <fileset file="@{source}" />
      </concat>
    </sequential>
  </macrodef>
Göran Engdahl
A: 

This solution is using Ant 1.8.1 -- I was trying to figure out how to concat a number of files in a specific order -- and it appeared that the only way to do this was with a filelist. Here's what I came up with:

Given a file with a list of filenames:

files.list:
-------------

file1.txt
file2.txt
file3.txt

Load this file into an ant property and use a filterchain to suffix the lines with ", " and to remove any line breaks:

<!-- put list in format for filelist element -->
<loadfile property="file.includes" srcFile="files.list">
    <filterchain>
        <suffixlines suffix=", "/>
        <striplinebreaks/>
    </filterchain>
</loadfile>

This will put the following value into the ${file.includes} property: "file1.txt, file2.txt, file3.txt,". This string is in the correct form to use in a filelist element now, so you can concat using the filelist and the ${file.includes} property:

<concat destfile="${dest.file}" fixlastline="yes">
    <filelist dir="${basedir}" files="${file.includes}"/>
</concat>

Hope this helps someone.

rayd