In ant, how can i check if a set of files (comma-separated list of paths) exist or not?
For example I need to check if all paths listed in myprop exist and if so i want to set a property pathExist:
<property name="myprop" value="path1,path2,path3"/>
So in the example all of path1 path2 path3 must exist to set pathExist to true, otherwise false.
I discovered that for a single resource I can use the resourceexist task, but i can't figure out how to use that with a comma-separated list of paths.
How can I check the existence for a set of paths? Thanks!
You can use a combination of a filelist, restrict and condition task for this.
In the below example a filelist is created from the property with the comma-separated list of files. Using restrict a list of the files that don't exist is found. This is placed in a property which will be empty if all the files are found.
<property name="myprop" value="path1,path2,path3"/>
<filelist id="my.files" dir="." files="${myprop}" />
<restrict id="missing.files">
<filelist refid="my.files"/>
<not>
<exists/>
</not>
</restrict>
<property name="missing.files" refid="missing.files" />
<condition property="pathExist" value="true" else="false">
<length string="${missing.files}" length="0" />
</condition>
<echo message="Files all found: ${pathExist}" />
You could use something like this to generate a failure message listing the missing files:
<fail message="Missing files: ${missing.files}">
<condition>
<length string="${missing.files}" when="greater" length="0" />
</condition>
</fail>
Bundled conditions are the shortest solution to check for existence of multiple dirs or files :
<condition property="pathExist">
<and>
<available file="/foo/bar" type="dir"/>
<available file="/foo/baz" type="dir"/>
<available file="path/to/foobar.txt"/>
...
</and>
</condition>
To check for a commaseparated list of path use Ant addon Flaka , f.e. :
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- when you have a cvs property use split function
to get your list to iterate over -->
<property name="checkpath" value="/foo/bar,/foo/baz,/foo/bazz"/>
<fl:for var="file" in="split('${checkpath}', ',')">
<fl:fail message="#{file} does not exist !!" test="!file.tofile.exists"/>
</fl:for>
</project>
Another possibility is the use of scriptcondition task with a jvm scripting language like groovy,beanshell .. etc.
This can be solved with the set operations of Ant´s resource collections. If you calculate the intersection of the list of required files with the list of existing files it must not differ from the list of required files. This shows how to do it:
<property name="files" value="a.jar,b.jar,c.jar"/>
<target name="missing">
<condition property="missing">
<resourcecount when="ne" count="0">
<difference id="missing">
<intersect>
<filelist id="required" dir="." files="${files}"/>
<fileset id="existing" dir="." includes="*.jar"/>
</intersect>
<filelist refid="required"/>
</difference>
</resourcecount>
</condition>
</target>
<target name="check" depends="missing" if="missing">
<echo message="missing: ${toString:missing}"/>
</target>
The check target reports the list of missing files only if a file is missing.
Related
I'm trying to base a task on whether a folder has content, not on whether it merely exists. I know there is probably a long winded solution, is there a better solution that I'm missing ?
I've tried two different methods to set a property depending on whether or not a folder has files in it.
My understanding is that 'available' does not permit wildcards like:
<available property="has.test.data" file="${test.data.dir}/**" type="file"/>
I tried this but it does not work if the folder (test.data.dir) does not exist:
<fileset id="test.data.files" dir="${test.data.dir}" includes="**/*" />
<condition property="has.test.data">
<resourcecount when="greater" count="0"> <fileset refid="test.data.files" /> </resourcecount>
</condition>
Ideally, I want to base a task on whether the folder actually has content, not just an empty folder.
You can use erroronmissingdir="false", to avoid the error for a non-existing directory. Add else="false" if you need the property to always exist
<?xml version="1.0" encoding="utf-8"?>
<project name="Test resourcecount" xmlns:if="ant:if">
<fileset id="test.data.files" dir="${test.data.dir}" includes="**/*" erroronmissingdir="false"/>
<condition property="has.test.data" else="false">
<resourcecount when="greater" count="0"> <fileset refid="test.data.files" /> </resourcecount>
</condition>
<echo if:true="${has.test.data}">${test.data.dir} is exists and is not empty</echo>
</project>
related Ant: How can I ignore build error if directory doesn't exist?
How can I use Ant to verify that the current working directory is located (arbitrarily deeply nested) under a certain path? For example, I want to execute a target only if the current directory is part of /some/dir/, for example if Ant is executed in directory /some/dir/to/my/project/.
The best I could come up with is a String contains condition:
<if>
<contains string="${basedir}" substring="/some/dir/"/>
<then>
<echo>Execute!</echo>
</then>
<else>
<echo>Skip.</echo>
</else>
</if>
This works for my current purpose but I'm afraid it might break some time in the future... for example when a build is executed in path /not/some/dir/ which is also contains the specified directory string.
Are there any more robust solutions like a startsWith comparison or even better a file system based check...?
There is no specific startswith condition in native Ant, but there is a matches condition that takes regular expressions.
As a side note, ant-contrib is rarely necessary for most build scripts, and will often lead to unreliable code. I would strongly recommend avoiding it.
Here's a sample script to illustrate how you can use the matches condition with native Ant. The test target is, of course, just for demonstration.
<property name="pattern" value="^/some/dir" />
<target name="init">
<condition property="basedir.starts.with">
<matches pattern="${pattern}" string="${basedir}" />
</condition>
</target>
<target name="execute" depends="init" if="basedir.starts.with">
<echo message="Executing" />
</target>
<target name="test">
<condition property="dir1.starts.with">
<matches pattern="${pattern}" string="/some/dir/" />
</condition>
<condition property="dir2.starts.with">
<matches pattern="${pattern}" string="/some/dir/to/my/project/" />
</condition>
<condition property="dir3.starts.with">
<matches pattern="${pattern}" string="/not/some/dir/" />
</condition>
<echo message="${dir1.starts.with}" />
<echo message="${dir2.starts.with}" />
<echo message="${dir3.starts.with}" />
</target>
My Ant script should download a ZIP file which contains a set-up file to be installed in a database (Oracle or PostgreSQL) and generate dumps. Different dumps are generated depending on the properties data provided in the set up file.
I have 3 properties files:
user.properties : this contains various details provided from Jenkins and apart from that a value: prepare.MTdump.generate=true
nonMT.properties
MT.properties
Is it possible in Ant to load the first properties file user.properties and depending upon the condition (e.g. if prepare.MTdump.generate=true) load MT.properties or if it's false load nonMT.properties?
I have been unable to add an IF condition to load the properties file. I even tried with the unless condition of <target> but have been unable to achieve the requirement.
If you are using ant-contrib, this should work:
<property file="user.properties"/>
<if>
<equals arg1="${prepare.MTdump.generate}" arg2="true"/>
<then>
<property file="MT.properties"/>
</then>
<else>
<property file="nonMT.properties"/>
</else>
</if>
Otherwise, you can just use conditions. Just run the loadProperties target below.
<property file="user.properties"/>
<target name="test.if.use.MT">
<condition property="useMT">
<equals arg1="${prepare.MTdump.generate}" arg2="true"/>
</condition>
<condition property="useNonMT">
<not>
<equals arg1="${prepare.MTdump.generate}" arg2="true"/>
</not>
</condition>
</target>
<target name="loadMTProperties" if="${useMT}" depends="test.if.use.MT">
<property file="MT.properties"/>
</target>
<target name="loadNonMTProperties" if="${useNonMT}" depends="test.if.use.MT">
<property file="nonMT.properties"/>
</target>
<target name="loadProperties" depends="loadMTProperties, loadNonMTProperties"/>
I have a property with a list of jars delimited with semicolons. The contents of the property is read from a file and not part of the build file, but it looks like this:
<property name="jars" value="a.jar;b.jar;c.jar"/>
And I would like to check if all the files are available. I know how to do it manually using:
<target name="opt">
<echo message="jars: ${jars}"/>
<condition property="found">
<and>
<available file="a.jar"/>
<available file="b.jar"/>
<available file="c.jar"/>
</and>
</condition>
<echo message="found: ${found}"/>
</target>
But how can this be done if the list of files is in a property and can not be written into the build file?
I need something like "apply and map available files". How can this be done?
You can use pathconvert to convert your file string to a fileset-include-pattern which can be used in a fileset; e.g.:
<pathconvert property="includespattern" pathsep=",">
<path path="a.jar;b.jar;c.jar;nonexisting.jar" />
<globmapper from="${basedir}/*" to="*" handledirsep="true" />
</pathconvert>
<fileset id="your.fileset" dir="${basedir}" includes="${includespattern}"/>
<!-- fileset will only contain existing files -->
<echo>${toString:your.fileset}</echo>
I want to compare the contents of two files (say file1.txt,file2.txt) using ANT.
if files content are same then it should set some 'property' to true, if contents are not same then it should set the 'property' as false.
Can anyone suggest me any ANT task that can do this.
Thanks in advance.
You can use something like:
<condition property="property" value="true">
<filesmatch file1="file1"
file2="file2"/>
</condition>
This will set the property only if the files are the same.
You can then check for the property, using
<target name="foo" if="property">
...
</target>
This is available in ant, with no added dependency, see here for other conditions.
I am in the same situation to compare two files and switch into different targets depending on files match or files mismatch...
Heres the code:
<project name="prospector" basedir="../" default="main">
<!-- set global properties for this build -->
<property name="oldVersion" value="/code/temp/project/application/configs/version.ini"></property>
<property name="newVersion" value="/var/www/html/prospector/application/configs/version.ini"></property>
<target name="main" depends="prepare, runWithoutDeployment, startDeployment">
<echo message="version match ${matchingVersions}"></echo>
<echo message="version mismatch ${nonMatchingVersion}"></echo>
</target>
<target name="prepare">
<!-- gets true, if files are matching -->
<condition property="matchingVersions" value="true" else="false">
<filesmatch file1="${oldVersion}" file2="${newVersion}" textfile="true"/>
</condition>
<!-- gets true, if files are mismatching -->
<condition property="nonMatchingVersion" value="true" else="false">
<not>
<filesmatch file1="${oldVersion}" file2="${newVersion}" textfile="true"/>
</not>
</condition>
</target>
<!-- does not get into it.... -->
<target name="startDeployment" if="nonMatchingVersions">
<echo message="Version has changed, update gets started..."></echo>
</target>
<target name="runWithoutDeployment" if="matchingVersions">
<echo message="Version equals, no need for an update..."></echo>
</target>
The properties are correct and change on changing file contents.
the task for nonMatchingVersions never gets started.