Expanding * in Ant copy task - ant

In ant copy task, in destination location there is a "random number" folder in the path. When i try to put a * in the path to handle it, Ant takes it literally, ie doesnt expand it, but creates a folder called "*" and copies there. How do I tell Ant to expand the * to actual folder name there (there is only 1 folder in there, so * wont expand to multiple folders)
<property name="dest" value="a/*/b/my.jar" />
<property name="src" value="my.jar" />
<copy file="${src}" tofile="${dest}" overwrite="true" verbose="true"/>

The copy task doesn't support wildcards in the tofile attribute. If the destination directory exists, but the destination file may not, then you can use a dirset to capture the directory. Something like:
<dirset dir="${basedir}" id="dest.dir">
<include name="a/*/b" />
</dirset>
<property name="dest" value="${toString:dest.dir}/my.jar"/>
<property name="src" value="my.jar" />
<copy file="${src}" tofile="${dest}" overwrite="true" verbose="true"/>
Instead of using the property helper (${toString:....}) syntax you might use the pathconvert task:
<pathconvert property="destdir" refid="dest.dir"/>
<property name="dest" value="${destdir}/my.jar"/>

Related

ant task to delete files and directory that start with the same name

In my folder example
I have a directory called test. It contains many subfolders
I also have files called test.properties and test.properties.sample
I am trying to create an ant script to remove the files and directory
Do I have to have 3 different tasks to delete these files?
For example
<delete dir="test" />
<delete file="test.properties" />
<delete file="test.properties.sample" />
I would rather have something like
<delete dir="test*" />
so it deletes everything in the folder that starts with test
Use a fileset to select files with a pattern, a dirset to select directories with a pattern.
This should do the job:
<delete>
<dirset dir="${basedir}" includes="test*" />
<fileset dir="${basedir}" includes="test*" />
</delete>

Get immediate subdirectory of a root directory containing a subdirectory

I have a following directory structure
root_dir
fixed_dir
random_dir
subdir1
subdir2
subdir2.1
subdir3
subdir3.1
subdir3.2
In the ANT build file I know the root_dir, fixed_dir, and one directory that is either random_dir or a subdirectory below random_dir (subdirX). I need to determine the path of random_dir given some subdirX. Is it possible to find this directory in ANT and if so, how?
Here is a tested solution for finding the immediate subdirectory of a root directory that contains some subdirectory subdirX at any level of nesting given the file structure provided in the question.
<property name="root.dir" location="${basedir}/root_dir" />
<property name="subdirX" value="subdir2.1" />
<target name="find-immediate-subdir-of-root-containing-subdirX">
<dirset dir="${root.dir}" includes="**/${subdirX}" id="mydirset" />
<pathconvert property="random_dir" pathsep="${line.separator}" refid="mydirset">
<mapper type="regexp"
from="^(${root.dir}${file.separator}[^${file.separator}]+).*"
to="\1"/>
</pathconvert>
<echo message="${random_dir}" />
</target>
Output
find-immediate-subdir-of-root-containing-subdirX:
[echo] /ant/project/basedir/root_dir/random_dir
BUILD SUCCESSFUL
Total time: 1 second
With Ant addon Flaka you'll get the parent as property of a file object (see Flaka Manual, section 3.7.2, i.e.
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- let standard ant tasks, i.e. echo
understand EL expresssions -->
<fl:install-property-handler />
<echo>#{file('${basedir}').parent}</echo>
<!-- or without fl:install-property-handler use fl:echo-->
<fl:echo>#{file('${basedir}').parent}</fl:echo>
</project>
so you would use :
#{file('${yoursubdir}').parent

Ant unzip task and only extracting files based on another directory

I have a zip file and, separately, a directory that contains some files. From the zip file I'd like to extract only those files that exist in the directory (performing a filename transformation on the files as they are being extracted..basically, I'm making backups of those files).
There is no problem doing something similar with a <copy> that has a fileset with a <present> element, but it doesn't seem to be working for me with unzip:
<unzip src="${cur.srcdir.live}" dest="${cur.srcdir.archive-files.dir}" overwrite="true">
<fileset dir=".">
<present present="both" targetdir="${cur.srcdir}" />
<type type="file" />
</fileset>
<globmapper from="*" to="*.${backup.suffix}" />
</unzip>
Has anyone done something like this before? This is Ant 1.8.0. Thanks!
I was able to solve my problem by "faking" the <present> selector that can be used in <copy>. Here's how:
First I used pathconvert to create a list of the files in my folder:
<pathconvert property="extract.list" pathsep="
">
<path>
<fileset dir="${extract.src.dir}" includes="${extract.src.dir.relpath}">
<type type="file" />
</fileset>
</path>
<map from="${extract.src.dir}\" to="" />
</pathconvert>
Notice the user of a map to have the list be relative paths instead of absolute paths. Plus, the delimiter is a newline.
Then this list gets written to a file:
<echo file="${props.tmp.file}" message="~~~~noop~~~~
${extract.list}" append="false" />
I put that "nooop" entry in there so that the file always has at least one line. This is important because of our next step where we use this as an includesfile. If the includesfile is empty, Ant interprets that as "allow anything"...but we want to make sure that an empty list results in nothing getting extracted from the zip.
Last step is to extract from the zip using our temp file from above as an includes file. The globmapper renames the files upon extraction, to the appropriate backup names:
<unzip src="${extract.archive}" dest="${extract.dest.dir}" overwrite="true">
<patternset>
<includesfile name="${props.tmp.file}" />
</patternset>
<globmapper from="*" to="*.${backup.suffix}" />
</unzip>
Adding this here in case someone needs to change the directory structure on extraction. I've spent so much trying to make this working. Ant Unzip task accepts cutdirsmapper.
<unzip dest="${build.dir}/packages">
<fileset dir="${src.dir}/packages" includes="*.pkg" />
<!-- Exctract build folder contents also moving one level up. -->
<cutdirsmapper dirs="1" />
<patternset>
<include name="build/" />
</patternset>
</unzip>
You can try calling unzip command via exec task.
The sample that I checked on Windows that refresh only changed files in dest.folder:
<property name="zip.file_name" value="Archive.zip"/>
<property name="src.folder" value="d:\"/>
<property name="dest.folder" value="d:\55"/>
<target name="unzip">
<echo>unzip -fo ${src.folder}${zip.file_name}</echo>
<exec dir="${dest.folder}" executable="cmd.exe" output="${src.folder}operation_result.txt">
<arg line="/c unzip -fo ${src.folder}${zip.file_name}"/>
</exec>
</target>
If you want to stay your original files you can use this command:
<arg line="/c unzip -foB ${src.folder}${zip.file_name}"/>
In case using -B parameter your original files (stored in folder) will be renamed - the tilde symbol will be appended. You get two sets of files - extracted from archive and old original files.
After that you can rename files with the help of move task.

Relocate contents of dynamic folder

I have a zip file which has one base folder inside it with other content inside that. I don't always know what that base folder is going to be called until I unzip it.
I'd like to move that base folder, and rename it at the same time, in ant - but can't seem to find out how. I've written code to extract the contents of the zip file to ${local.sdk.dir}/temp/ but from here i can't work out how to rename/move the extracted folder
<move todir="${local.sdk.dir}/${remote.sdk.file.name}">
<fileset dir="${local.sdk.dir}/temp/<WHAT_DO_I_PUT_HERE?>"></fileset>
</move>
also tried
<move todir="${local.sdk.dir}/${remote.sdk.file.name}" includeEmptyDirs="yes" verbose="true">
<fileset dir="${local.sdk.dir}/temp/" >
<include name="**/*" />
</fileset>
</move>
and played about with this, but closest I can get without ant throwing an error is to copy the contents of the temp dir, not the base folder within temp.
You can do all this in one step - copy from the zip file and rename the files changing the dir name as you copy. The copy task accepts a nested resource collection, so you can use a zipfileset to specify the files to copy directly from the zip file.
In order to rename the files as they are copied, you can use a mapper, which the copy task also takes as a nested element. In this case, a cutsdirmapper looks like the tool for the job.
So, if I've understood what you want to do correctly, something like this should work:
<copy todir="${local.sdk.dir}/${remote.sdk.file.name}">
<zipfileset src="${your.zip.file}" />
<cutdirsmapper dirs="1" />
</copy>
cutdirsmapper is only available in Ant 1.8.2 onward, so if you're using an earlier version, you could try a regexpmapper:
<regexpmapper from="[^/]*(.*)" to="\1" />
Similar to this question
<target name="relocate_sdk_folder">
<path id="sdk_folder_name">
<dirset dir="${local.sdk.dir}/temp/">
<include name="*"/>
</dirset>
</path>
<property name="sdk_folder_name" refid="sdk_folder_name" />
<echo message="renaming ${sdk_folder_name} to ${remote.sdk.file.name}" />
<move file="${sdk_folder_name}" tofile="${local.sdk.dir}/${remote.sdk.file.name}" />
</target>

Ant - using variables in .properties files

I am trying to replace placeholders in source files with values defined in a .properties file using the copy task with **
My build.xml contains
<target name="configure">
<echo message="Creating DB configuration" />
<copy todir="${dir.out}" overwrite="true">
<fileset dir="${dir.in}" />
<filterchain>
<expandproperties/>
<replacetokens begintoken="<" endtoken=">" propertiesResource="conf.properties" />
</filterchain>
</copy>
</target>
A sample from the conf.properties:
tbs.base_directory = d:/oracle/oradata/my_app
tbs.data_file = ${tbs.base_directory}/data01.dbf
I want to refer from within the .properties file to variables, in this case I would like to substitute tbs.base_directory in tbs.data_file.
Unfortunately it is not substituted. Any ideas?
Thanks
Problem is that expandproperties applies to copied file not to the property resource you are using to define your tokens. A possible solution is to first load conf.properties to force properties expansion and dump it into a temporary file that is used for token substitution. Something like the following should work:
<target name="configure">
<echo message="Creating DB configuration" />
<!-- force expanding properties in tokens property file -->
<loadproperties srcfile="conf.properties" />
<!-- dump expanded properties in a temp file -->
<echoproperties prefix="tbs" destfile="conf.expanded.properties"/>
<copy todir="${dst.out}" overwrite="true">
<fileset dir="${dir.in}" />
<filterchain>
<expandproperties/>
<!-- use temporary file for token substitution -->
<replacetokens begintoken="<" endtoken=">" propertiesResource="conf.expanded.properties" />
</filterchain>
</copy>
<!-- delete temp file (optinal)-->
<delete file="conf.expanded.properties"/>
</target>
Drawback of this solution is that it only works as long as you can select the properties to write in the temporary file (i.e all properties in the conf.properties file starts with the same prefix).

Resources