Specifying Ant file sets with properties

Posted on November 18, 2009

When specifying a set of files in Ant usually the fileset type is the way to go. However, I ran into a situation where I needed to specify a file set by a list of directories in a property.

For instance suppose there is a directory res with the sub-directories eggs, milk and bread. When packaging a JAR file, only some of the directories in res shall be included, depending on a customizable property:

res.dirs = eggs,bread

To my best knowledge Ant does not provide a straight forward way to get a file set out of such a property. My first attempt was to use the includes attribute of the fileset type:

<fileset dir="res" includes="${res.dirs}" />

The problem here is that this only specifies directories but no files and thus the file set is empty. Next I tried using the dirset type in a similar way and then the set indeed contained the specified directories but not the files within the directories (well, it's a dir set).

The crucial point here is that Ant explicitly expect files to be specified, e.g. like this:

res.dirs = eggs/**/*,bread/**/*

But setting this in a properties file is ugly, especially if the list is of directories is long.

The solution is to use the pathconvert task to transform a directory list like eggs,bread to eggs/**/*,bread**/*:

<pathconvert property="res.files" pathsep=",">
  <dirset dir="${basedir}/res" includes="${res.dirs}" />
  <mapper type="regexp" from="^(.*)$$" to="\\1/**/*" />
  <map from="${basedir}/res/" to="" />
</pathconvert>

The dirset type specifies the dirs to convert the path name for. The mapper appends /**/* to each path. Finally the map strips off the absolute portion of the path to get paths relative to the directory res. The result is stored in the propery res.files.

This property can now be used for the includes attribute of a fileset type:

<fileset dir="res" includes="${res.files}" />

Et voilĂ , now there is a file set for all files in the directories given by the property res.dirs.