Ant concat fileset separator - ant

When using concat with fileset in Ant, how do I make an action happen for each element in the fileset. Such as, adding a string:
<fileset dir="${project.path.scripts-library}"
excludes="!*.js, **/*.bak, **/dev.*"
>
<type type="file" />
<include name="**/0*.js" />
<include name="**/1*.js" />
<string>test</string>
</fileset>
Or echoing the current file name for each file in the fileset (and, how do I GET the file name for the current file???):
<fileset dir="${project.path.scripts-library}"
excludes="!*.js, **/*.bak, **/dev.*"
>
<echo file="${app.path.file}"
append="true"
message=",${the.file.name}" />
<type type="file" />
<include name="**/0*.js" />
<include name="**/1*.js" />
</fileset>

I think there is no such thing in default ant. The closest one is <apply>, but it's system specific:
<apply executable="echo"> <!-- run this command with each file name -->
<fileset dir="/tmp" includes="**/*.*"/>
</apply>
Also you can install ant-contrib to enable <for> task:
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<for param="file">
<path>
<fileset dir="/tmp" includes="**/*.*"/>
</path>
<sequential> <!-- run any task here -->
<echo>file [#{file}]</echo>
</sequential>
</for>

Related

apache Ant basename issue with empty input strings

I have the below ant code which gives basename (for ex: abc_01142018.txt) of the file from location input.dir. When the file is available, it works as expected.But when there are no files in input.dir it is picking up a value which I am not passing. I am expecting it to be empty value.
I read about basename and its not mentioned anywhere about how basename works when the input parameter is empty.
<path id="ref-id">
<fileset dir="${input.dir}">
<include name="abc*.txt"/>
</fileset>
</path>
<property name="input.files" refid="ref-id"/>
<basename property="input.file" file="${input.files}" />
There's no need to use Ant's path type or basename task if all you want is a list of file names without parent directories. The fileset type already does this, so just reference its ID instead.
Example:
<target name="test">
<touch file="exists1.txt" />
<touch file="exists2.txt" />
<fileset dir="." id="exists">
<include name="exists*.txt" />
</fileset>
<fileset dir="." id="doesnotexist">
<include name="doesnotexist*.txt" />
</fileset>
<property name="exists" refid="exists" />
<property name="doesnotexist" refid="doesnotexist" />
<echo message="${exists}" />
<echo message="${doesnotexist}" />
</target>

Ant - Using Resource Unions with Macrodef

I have an Ant Macrodef that has an <element> placeholder. I am attempting to use the <element> to pass a resourceCollection for processing. The contents of the <element> is populated correctly prior to invoking the macrodef. Unfortunately, during invocation, it comes in as empty.
Macrodef:
<macrodef name="doStuff" description="Amazing macrodef that fails me.">
<element name="fs" optional="true" description="resource/element/fileset to be manipulated />
<sequential>
<echo message="fs: ${toString:fs}" />
<pathconvert property="outputProp" pathsep=" ">
<fs />
</pathconvert>
</sequential>
</macrodef>
and it is invoked via the following pieces of a build.xml file I have:
<fileset id="files1" dir=".">
<include name="inc/*" />
<include name="lib/*" />
</fileset>
<fileset id="files2" dir=".">
<include name="bin/*" />
</fileset>
<union id="allFiles">
<resources refid="files1" />
<resources refid="files2" />
</union>
<target name="doStuffToFiles">
<doStuff>
<fs>
<resources refid="allFiles" />
</fs>
</doStuff>
</target>
I'm unsure why, but going through the union and resources, instead of using a direct fileset with a refid, seemed to be confusing my Ant setup. The following has worked for me on Ant 1.9.2
<macrodef name="doStuff" description="Amazing macrodef that fails me.">
<element name="fs"
optional="false"
description="resource/element/fileset to be manipulated />
<sequential>
<pathconvert property="outputProp" pathsep=" ">
<fs />
<map from="${basedir}/" to=""/>
</pathconvert>
</sequential>
</macrodef>
<target name="doStuffToFiles">
<fileset id="files1" dir=".">
<include name="inc/**"/>
<include name="lib/**"/>
</fileset>
<fileset id="files2" dir=".">
<include name="bin/**"/>
</fileset>
<doStuff>
<fs>
<fileset refid="files1" />
<fileset refid="files2" />
</fs>
</doStuff>
</target>

how to use<MacroDef> for recourcecount of all file in folder with different extension

While going through the scenario what i got is that folder collection of different extension file i have use resource count for all extension if i have 3 different extension file than try to get resource count of all file differ with extension
Eg:
<resourcecount property="firstfile">
<fileset dir="${basedir}">
<include name="*.xml" />
</fileset>
</resourcecount>
<echo message="There are ${firstfile} xml in This Folder ${basedir}" />
<resourcecount property="SecondFile">
<fileset dir="${basedir}">
<include name="*.jar" />
</fileset>
</resourcecount>
<echo message="There are ${SecondFile} xml in This Folder ${basedir}" />
How can i use the macrodef for this condition which help in count all file with it
You can do this in many ways, including using plugins, such as ant-contrib, or using ant language extensions. But all of them are overkill compared to this simple build script:
<target name="count">
<countresources type="xml" />
<countresources type="java" />
<countresources type="cpp" />
</target>
<macrodef name="countresources">
<attribute name="type" />
<sequential>
<resourcecount property="#{type}.count">
<fileset dir="${basedir}">
<include name="*.#{type}" />
</fileset>
</resourcecount>
<echo message="There are ${#{type}.count} #{type} files in folder ${basedir}" />
</sequential>
</macrodef>
Hope this helps.

Generating MD5 for files in an ant-contrib for loop in ANT

I am selecting set of files using file set and then using them to generate the checksum of all the files in the selected fileset
here is my script
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="MyTask1" basedir="." default="jar">
<property name="cms.dir" value="D:\Test" />
<property name="comma" value="," />
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<target name="A">
<fileset id="src.files" dir="${cms.dir}" casesensitive="yes">
<include name="**/*.uim"/>
<include name="**/*.properties"/>
<include name="**/*.txt"/>
</fileset>
<pathconvert pathsep="${line.separator}" property="sounds" refid="src.files">
<!-- To get the names of the files only then use mapper-->
<!-- <mapper type="flatten" />-->
</pathconvert>
<delete file="sounds.txt"/>
<for list="${sounds}" delimiter="${line.separator}" param="mod">
<sequential>
<checksum file="#{mod}" property="MD5_Value"/>
<echo file="sounds.txt" append="true">#{mod}${comma}${MD5_Value}${line.separator}</echo>
</sequential>
</for>
<!--<checksum file="Test.txt" property="foobarMD5"/>-->
<!--<echo file="sounds.txt">${foobarMD5}</echo>-->
</target>
</project>
However its failing and its generating duplicate MD5 value here is my output
D:\Test\Test1.txt,6d326741a99efbcda928e5096b43cb9a
D:\Test\Test2.txt,6d326741a99efbcda928e5096b43cb9a
Any help ...
The checksum task can process filesets...
<checksum>
<fileset dir=".">
<include name="foo*"/>
</fileset>
</checksum>
Lot simpler than using the for task, which is not part of standard ANT.

Combine filesets using Ant

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!
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.
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>
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.

Resources