Ant <copy todir> zipfileset with prefix - ant

Let's say that C:/dir2/ has one file called file2.txt
And that C:/dir3/has one file called file3.txt
This ant script:
<copy todir="C:/dir1">
<zipfileset dir="C:/dir2" prefix="dirprefix2"/>
<zipfileset dir="C:/dir3" prefix="dirprefix3"/>
</copy>
copies the files to:
C:/dir1/file2.txt
C:/dir1/file3.txt
But I wanted it to copy to:
C:/dir1/dirprefix2/file2.txt
C:/dir1/dirprefix3/file3.txt
Anyone knows what I am doing wrong?

The attribute prefix is used only when creating archives.
The following should work fine:
<copy todir="C:/dir1/dirprefix">
<zipfileset dir="C:/dir2"/>
</copy>
Alternatively, you can use macros:
<macrodef name="mycp">
<attribute name="dir"/>
<attribute name="todir" default="C:/dir1"/>
<attribute name="prefix"/>
<sequential>
<copy todir="#{todir}/#{prefix}">
<fileset dir="#{dir}/"/>
</copy>
</sequential>
</macrodef>
then you will have one line per directory, like this:
<mycp dir="C:/dir2" prefix="dirprefix2"/>
<mycp dir="C:/dir3" prefix="dirprefix3"/>
...

Related

How do I exclude a folder in an ant jar task?

I am trying to build a java project using ant. I have to exclude a particular directory from base directory for jar packaging. Here is the code snippet.
<target name="jar" depends="wsdl2java,oss.init,oss.request.compile">
<copy todir="${build.lib.dir}">
<fileset dir="${oss.lib.dir}" includes="**/*.*" excludes="**/weblogic.jar"/>
</copy>
<copy todir="${build.conf.dir}">
<fileset dir="${oss.conf.dir}" includes="**/*.*"/>
</copy>
<copy todir="${oss.build.dir}">
<fileset dir="${oss.run.dir}" includes="**/*.*"/>
</copy>
<jar destfile="${oss.build.dir}/osstool2.5.5.jar" basedir="${oss.class.dir}" excludes="**/dms/*">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
<attribute name="Created-By" value="${owner}"/>
<attribute name="Class-Path" value=". lib/antlr-runtime-3.0.1.jar.jar lib/log4j.jar
lib/commons-discovery-0.2.jar lib/commons-logging-1.1.1.jar
lib/spring.jar lib/axis.jar lib/axis-ant.jar lib/jaxrpc-api.jar
lib/webserviceclient.jar lib/webserviceclient+ssl.jar
lib/wlclient.jar lib/wsdl4j-1.5.1.jar lib/wsse.jar lib/ala-castor.jar lib/log4j.jar lib/log4j.jar lib/xercesImpl.jar
lib/ala-nbi-commons-1.3.0.jar lib/ala-nbi-notification-plugins.jar lib/ala-nbi-webservice-client-1.3.0.jar
lib/axis.jar lib/axis-ant.jar lib/dom4j-1.6.1.jar lib/jaxrpc-api.jar lib/webserviceclient.jar lib/webserviceclient+ssl.jar
lib/wlclient.jar lib/wsdl4j-1.5.1.jar lib/wsse.jar lib/commons-logging.jar">
</attribute>
</manifest>
</jar>
</target>
What am I missing here?
Thanks in advance.

Update fileset using ant dynamically

I would like to create a jar file dynamically depending on selected java modules
Here is the part of the ant script which does that.
<property name="modules.selected" value="A,C,F" />
<for list="${modules.selected}" param="module">
<sequential>
<echo>Module chosen ${basedir}/#{module}/src</echo>
<copy todir="${build.dir.src}" overwrite="true">
<fileset dir="${basedir}/#{module}/src">
<include name="**/*.${src.valid.exts}" />
</fileset>
</copy>
</sequential>
</for>
In the above script I am selecting a module and then constructing a directory and copying all the modules present in the directory to a location (build/src).
But I really dont like the logic mentioned above would like to change to include all the required modules in a fileset and use the populated fileset to copy.
Here is the logic I am looking for
<fileset id="required-modules" dir="${basedir}/#{module}/src">
<for list="${modules.selected}" param="module">
<sequential>
<echo>Module chosen ${basedir}/#{module}/src</echo>
<include name="**/*.${src.valid.exts}" />
</sequential>
</for>
</fileset>
<copy todir="${build.dir.src}" overwrite="true">
<fileset refid="required-modules" />
</copy>
Could anyone update the above script to make it work.

How can I process only files that have changed?

At the moment I'm doing this:
<delete dir="${RSA.dir}/file1" />
<copy todir="${RSA.dir}/file1" >
<fileset dir="${CLEARCASE.dir}/file1" />
</copy>
and repeating the same thing for other files - but it takes a long time.
I only want to delete and copy files that have been updated, with their modified date in clearcase later than that in RSA.
How can I do that?
Look into the sync task.
If you want to do it based on file contents, and ignore the timestamp, I think this macro will do that:
<macrodef name="mirror" description="Copy files only if different; remove files that do not exist in dir. This works similiar to robocopy /MIR." >
<attribute name="dir"/>
<attribute name="todir"/>
<sequential>
<copy overwrite="true" todir="#{todir}">
<fileset dir="#{dir}">
<different targetdir="${todir}"/>
</fileset>
</copy>
<delete includeemptydirs="true">
<fileset dir="#todir}">
<present targetdir="${dir}" present="srconly"/>
</fileset>
</delete>
</sequential>
</macrodef>
You need to use a selector on a FileSet. Something like this:
<fileset dir="${your.working.dir}/src/main" includes="**/*.java">
<different targetdir="${clean.clearcase.checkout}/src/main"
ignoreFileTimes="false"
ignoreContents="true" />
</fileset>
That compares your working dir to a clean checkout you have elsewhere, and returns the files whose last modified times have changed. You can use the fileset as the argument for a <delete> or a <copy>.

Ant: copy the same fileset to multiple places

I need an Ant script that will copy one folder to several other places. As a good obedient programmer, I want not to repeat myself. Is there any way of taking a fileset like this:
<copy todir="${target}/path/to/target/1">
<fileset dir="${src}">
<exclude name='**/*svn' />
</fileset>
</copy>
And storing the fileset in a variable so it can be re-used?
Declare an id attribute on the fileset and then reference it in each copy task.
For example:
<project name="foo">
<fileset id="myFileSet" dir="${src}">
<exclude name='**/*svn' />
</fileset>
...
<target name="copy1">
<copy todir="${target}/path/to/target/1">
<fileset refid="myFileSet"/>
</copy>
</target>
<target name="copy2">
<copy todir="${target}/path/to/target/2">
<fileset refid="myFileSet"/>
</copy>
</target>
</project>
Rich's answer is probably better for your specific problem, but the generic way of reusing code in Ant is a <macrodef>.
<macrodef name="copythings">
<attribute name="todir"/>
<sequential>
<copy todir="#{todir}">
<fileset dir="${src}">
<exclude name='**/*svn' />
</fileset>
</copy>
</sequential>
</macrodef>
<copythings todir="/path/to/target1"/>
<copythings todir="/path/to/target2"/>
Upvoted first answer already, but you can also use a mapper to copy to multiple destinations.

How to <copy> in a <macrodef> in ant?

I'm trying to copy files in a macro, like so:
<project name="why" default="go">
<macrodef name="copy-some-stuff">
<attribute name="file.name" />
<copy todir="/var/tmp">
<fileset file="${file.name}" />
</copy>
</macrodef>
<target name="go">
<copy-some-stuff file.name="/etc/hosts" />
</target>
</project>
but I get the following
BUILD FAILED
b.xml:3: macrodef doesn't support the nested "copy" element.
Any ideas, other than "yes, indeeed, macrodef doesn't support the nested "copy" element." I got that much. I'm looking for why this limitation is here and a possible workaround (without using antcall).
Try surrounding the <copy> element with <sequential>:
<macrodef name="copy-some-stuff">
<attribute name="file.name" />
<sequential>
<copy todir="/var/tmp">
<fileset file="#{file.name}" />
</copy>
</sequential>
</macrodef>

Resources