How to create directories specified by a mapper in Ant - ant

Given a fileset
<fileset id="myFiles" dir=".">
<include name="**/*.file"/>
</fileset>
How do I create a sub-directory at each file in the set, named after the filename without the extension?
For example, given the files folderA/X.file and folderA/folderB/Y.file, I want to create the directories folderA/X and folderA/folderB/Y

The ant touch task supports creating files, parent dirs and filename mapping, so can be used to achieve this:
<target name="mkdirs">
<touch mkdirs="true">
<fileset dir="the_dir"/>
<mapper type="glob" from="*.file" to="the_dir/*/.tmp" />
</touch>
<delete>
<fileset dir="the_dir" includes="**/.tmp"/>
</delete>
</target>
This creates temporary files in target dirs (creating the dirs if the don't exist) then deletes the temporary files leaving the dirs you wanted.

You would be using for task to iterate on your file list. But I have not come across any substring type of utility in Ant which you can use to strip the extension and create the directory. Do search for this utility, if its not there then you need to implement an Ant task to do that.

Sorry to answer my own question. Unless someone knows otherwise, there appears to be no way for out-of-the-box ANT to create directories (e.g. using mkdir) relative to entries in a fileset.
Ant-Contrib contains useful for loop tasks, as Bhushan suggests, which could possibly perform this sort of task.
Had some better things to be getting on with, so in the end, I just wrote a batch file called by an ANT task (apply tasks can iterate over filesets).
<apply executable="cmd" failonerror="1">
<arg value="/c"/>
<arg line="build\tools\makeRelDir.bat"/>
<fileset dir=".">
<include name="**/*.file"/>
</fileset>
</apply>
where the batch file does this:
mkdir %~dp1%~n1
(Why is it so hard to do something some simple in ANT? Am I missing something?)

Related

Update destination directory with new files (if modified) using ant

I'm facing a problem with ant "copy". Here is my requirement:
I want to sync 2 dirs(dir1 and dir2) but i want to keep the extra files/dirs present in dir2. My aim is i want to copy dir1 contents(if modified ) to dir2 but want to keep any additional files/dirs present in dir2.
I tried ant's sync task, but it is trying to keep both dirs in sync ie., it is deleting extra contents present in dir2. I don't find any flag to disable this feature:
<sync todir="dir2" failonerror="true" verbose="true">
<fileset dir="dir1" excludes="*.svn" />
</sync>
I tried ant's copy with "modified" selector, but its also doing the same: :(
<copy todir="dir2" failonerror="true">
<fileset dir="dir1" excludes="*.svn" >
<modified/> <!-- Copies only modified files -->
</fileset>
Can any one suggest, how can i achieve my requirement with ant?
By default, the ANT copy task does not overwrite files:
<copy todir="target/dir2" verbose="true" overwrite="false">
<fileset dir="src/dir1"/>
</copy>
The copy task will also detect if the file has changed.
The copy task will not delete files, so I don't understand why your second example (using a modified selector) did not work.

Apache Ant create new fileset from existing fileset with filenames renamed

I have the following fileset in my Apache Ant build file (BuildFilesetXML.xml):
<fileset id="XMLFileset" dir="mydir/myxml">
<include name="**/1.xml"/>
<include name="**/2.xml"/>
</fileset>
I want to create dynamically in a different build file (BuildFilesetLog.xml) (do not know the contents of "XMLFileset" in my 2nd build file) a new fileset named "LOGFileset" that will have the same contents of "XMLFileset" but with names renamed to .log. So, in runtime it will have the same structure as the following fileset:
<fileset id="LOGFileset">
<include name="**/1.log"/>
<include name="**/2.log"/>
</fileset>
Can this be done in Ant?
Thanks
No, but some tasks support mappers. For an example see the following answer:
Change directory of FileList when referencing it

Using Ant to delete a file based on existence of another file

I need to write an ant task to selectively delete files.
In a directory, I have the following jars:
acme.jar
acme-201105251330.jar
I want to delete acme.jar because acme-*.jar exists.
Here's what I've tried:
<target name="-check-use-file">
<available property="file.exists">
<filepath> <fileset dir=".">
<include name="./test-*.jar"/> </fileset>
</filepath>
</available>
</target>
<target name="use-file" depends="-check-use-file" if="file.exists">
<!-- do something requiring that file... -->
</target>
Thanks
Have a look at If/Unless Attributes, examples given there seem to be exactly what you are looking for.

Ant Copying Empty Directories

I am still very new to ant and, although I know coldfusion, I don't know very much about java conventions, but I know that ant is built using java conventions. That being said I am working on an ant process to copy a project to a temp folder, change some code in the project, and then push the temp directory up to an FTP. I am trying to exclude all of my git, eclipse, and ant files from the copy so that my testing platform doesn't get cluttered. I setup a target to do the copy, but it seems that Ant not only is ignoring my excludes (which I am sure I wrote wrong), but it is only copying top level directories and files. No recursive copy. My current target is:
<target name="moveToTemp" depends="init">
<delete dir="./.ant/temp" />
<mkdir dir="./.ant/temp" />
<copy todir="./.ant/temp">
<fileset dir=".">
<include name="*" />
<exclude name=".*/**" />
<exclude name=".*" />
<exclude name="build.xml" />
<exclude name="settings.xml" />
<exclude name="WEB-INF/**" />
</fileset>
<filterset>
<filter token="set(environment='design')" value="set(environment='testing')" />
</filterset>
</copy>
</target>
I know that I am not doing my excludes right, but I don't know what I am doing wrong with them. I see double asterisks (**) used all the time in Ant but I can't figure out
By default an Ant fileset will (recursively) include all files under the specified directory, equivalent to:
<include name="**/*" />
That's the implicit include. If you supply an include, it overrides the implicit one.
Your include
<include name="*" />
Says 'match any file in the fileset directory', but that excludes traversal of subdirectories, hence your issue. Only files and the top-level directories are being copied.
See Patterns in the Ant docs for directory-based tasks: ** matches any directory tree (zero or more directories).
For your case you should be able to simply remove the 'include', so that the implicit 'include all' applies.
Suggest you also investigate the defaultexcludes task, which lets you set up this sort of thing once for the whole project.
Responding to the title of the question. You can include copy of empty directories as follows. (includeemptydirs attribute)
Example:
<copy includeemptydirs="true" todir="${directory}${file.separator}sentinel_files">
<fileset dir="${basedir}${file.separator}sentinel_files"/>
</copy>
Use the documentation provided in:
https://ant.apache.org/manual/Tasks/copy.html

per-file dependencies in ant

I have a set of input files, each of which is processed to generate an output file. In one case it's hibernate xml files as input, and java files as output, but that isn't the only case I have to deal with.
In make, I would have set up a rule to tell it how to generate a .java file from an .hbm.xml file (modulo the .hbm.xml specifying a different class name to generate), and modifying a single .hbm.xml files would trigger the build of a single .java file.
How do I express the dependencies in ant so it will only build the out of date .java files and not all of them just because one .hbm.xml changed?
I'm looking at apply and up-to-date, but not seeing a solution yet...
Have you looked at ant-contrib outofdate task?
The example at the end of the doc looks like something you could use:
<outofdate property="manual.outofdate"
outputsources="grammer.sources">
<sourcefiles>
<fileset dir="${src.grammer}" includes="**/*.y"/>
</sourcefiles>
<mapper type="glob" dir="${src.grammer}" from="*.y" to="${gen.grammer}/*.c"/>
<mapper type="glob" dir="${src.grammer}" from="*.y" to="${gen.grammer}/*.h"/>
<sequential>
<shellscript shell="bash">
cd ${gen.grammer}
for g in ${grammer.sources}
do
gengrammer $g
done
</shellscript>
</sequential>
</outofdate>
Also note that you might use ant-contrib "for" task in the body of the outofdate task.
To initialize ant-contrib do this:
<property name="ant-contrib.jar" location="..."/>
<taskdef
resource="net/sf/antcontrib/antlib.xml"
uri="http://ant-contrib.sourceforge.net"
>
<classpath>
<pathelement location="${ant-contrib.jar}"/>
</classpath>
</taskdef>

Resources