22

I have 2 different filesets defined in Ant as follows:

<fileset id="fileset1" dir="${classes.dir}">
</fileset>

<zipfileset id="fileset2" src="myArchive.zip" includes="**/*.class">
</zipfileset>

I want to create a third fileset which is the union of both the above filesets

<fileset id="merged">
</fileset>

Can someone tell me how to do this ? Is it even possible to do something like that ? Thanks in advance!

Kryptic Coder
  • 612
  • 2
  • 8
  • 20

3 Answers3

18

One way to do this is with Ant resource collections, in particular a union.

<fileset id="fileset1" dir="${classes.dir}" />
<zipfileset id="fileset2" src="myArchive.zip" includes="**/*.class" />

<union id="onion">
    <resources refid="fileset1" />
    <resources refid="fileset2" />
</union>

Then you can refer to the 'onion' anywhere you might use a fileset, e.g.

<copy todir="dest">
    <resources refid="onion" />
</copy>

I recommend using generic resources elements rather than filesets for maximum flexibility.

martin clayton
  • 76,436
  • 32
  • 213
  • 198
  • 6
    Union does not work for me - I am getting "xxx doesn't denote a fileset" in my case, because target which I need to invoke expects fileset explicitly: `` :-\ – alexandroid Mar 03 '13 at 23:25
  • @alexandroid Which target expects a fileset ? Perhaps you may patch it to accept a resource collection instead !? Many ant tasks where redesigned for resource collections in version 1.7 – Rebse Mar 04 '13 at 20:15
  • Its the target from the script / package I do not have direct control of at the moment, unfortunately (I am only calling it) – alexandroid Mar 06 '13 at 18:45
  • Works but is a little cumbersome if you have three or more filesets. Is there a way to get a fileset from multiple directories? – The Unknown Dev Mar 25 '15 at 20:12
  • Maybe try [`multirootfileset`](https://ant.apache.org/manual/Types/multirootfileset.html)? – ravilov Jul 30 '19 at 01:10
2

Try this: I think it should work, since <fileset> is an implicit <patternset>.

<fileset id="fileset1" dir="${classes.dir}">
</fileset>

<zipfileset id="fileset2" src="myArchive.zip" includes="**/*.class">
</zipfileset>

EDIT: odd. This perhaps?

<patternset id="merged">
  <patternset refid="fileset1" />
  <patternset refid="fileset2" />
</patternset>
Femi
  • 64,273
  • 8
  • 118
  • 148
0

problem with fileset is, that it requires a directory as a base upon it applies the patternset. Which means you have to find a common base directory that is shared by all filesets.

A <pathconvert> Task can take filesets via refid. You can put several filesets (e.g. from various build targets to assemble a compound set in a root/main target for a modular build environment):


<project name="root" basedir="." xmlns:if="ant:if" xmlns:unless="ant:unless">
<!-- 
it's important to take the xmlns:features in your project head 
otherwhise this code won't work 
-->
    <target name="init">
        <!-- set some common prerequisites -->
        <property name="prerequisite.property.xyz" value="xyz" />
    </target>

    <target name="targetA" depends="init">
        <fileset dir="${common.basedir}${file.separator}${targetA.subdir}" id="targetA.fileset">
            <include name="**/*.html" />
        </fileset>
        <property name="targetA.fileset.exists" value="true" />
    </target>

    <target name="targetB" depends="init">
        <fileset dir="${common.basedir}${file.separator}${targetB.subdir}" id="targetB.fileset">
            <include name="**/*.java" />
        </fileset>
        <property name="targetB.fileset.exists" value="true" />
    </target>

    <target name="targetC" depends="init">
        <fileset dir="${common.basedir}${file.separator}${targetC.subdir}" id="targetC.fileset">
            <include name="**/*.class" />
        </fileset>
        <property name="targetC.fileset.exists" value="true" />
    </target>

    <target name="root" depends="init">
        <pathconvert property="all.files.as.commaseparated.path" pathsep="," dirsep="/">
            <fileset refid="targetA.fileset" if:true="${targetA.fileset.exists}" />
            <fileset refid="targetB.fileset" if:true="${targetB.fileset.exists}" />
            <fileset refid="targetC.fileset" if:true="${targetC.fileset.exists}" />
            <map from="${common.basedir}/" to="" />
        </pathconvert>
        <!-- assemble new fileset from paths as comma separated property string -->
        <fileset id="new.refid" dir="${common.basedir}" includes="${all.files.as.commaseparated.path}" />
    </target>
</project>

This can be called via command line like:

ant targetA targetB targetC root

or

ant targetA root

Be aware that root is always the last target being called.