Ant Dirset of all Sub-Directories which contain Files - ant

I need to make a dirset containing all low-level directories which contain files.
So for example a structure like:
.
├── _a
├── _b
| ├── file1.class
| └── file2.class
├── _c
| └── _d
| └── file3.class
├── _e
| ├── _f
| └── _g
└── _h
└── file4.class
Would result in a dirset of the directories:
./b/
./c/d/
./h/
How could I achieve this?

I found the solution, it was to first create a fileset in the directory that I needed to scan, then use a pathconvert in order to get the parent directories of all files and to get the relative path.
All that was left was to create a dirset with an includes that specifies the paths from the pathconvert (it also removes duplicate directory entries).
<pathconvert pathsep="," property="filePaths">
<map from="${basedir}/" to="" />
<!-- get parent of file -->
<regexpmapper from="(.*)\${file.separator}" to="\1" />
<path>
<!-- change dir to your directory -->
<fileset dir="${basedir}/dir" casesensitive="yes">
<include name="**/*.*" />
</fileset>
</path>
</pathconvert>
<dirset dir="${basedir}/" casesensitive="yes" includes="${filePaths}" />

Not sure in which task you wanted.
Anyways, try fileset as given below:
<fileset dir="${base.dir}" casesensitive="yes">
<include name="**/*.*"/>
</fileset>

Related

Copying files from source directory to destination directory using ant

I want to copy some specific files from source directory to destination directory on below condition using ANT.
Source folder contains the following files
35001_abc.sql
38001_abc.sql
38002_abc.sql
39001_abc.sql
I want to copy the files with filenames starting with 36000 and above.
The Output directory should contain the following files
38001_abc.sql
38002_abc.sql
39001_abc.sql
One idea is to use a regular expression on the filename to restrict ranges of digits.
Example
├── build.xml
├── src
│   ├── 35001_abc.sql
│   ├── 38001_abc.sql
│   ├── 38002_abc.sql
│   ├── 39001_abc.sql
│   ├── 41001_abc.sql
│   └── 46001_abc.sql
└── target
├── 38001_abc.sql
├── 38002_abc.sql
├── 39001_abc.sql
├── 41001_abc.sql
└── 46001_abc.sql
build.xml
<project name="demo" default="copy">
<property name="src.dir" location="src"/>
<property name="build.dir" location="target"/>
<target name="copy">
<copy todir="${build.dir}" overwrite="true" verbose="true">
<fileset dir="${src.dir}">
<filename regex="^(3[6-9]|[4-9]\d)\d{3}_abc.sql$"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="${build.dir}"/>
</target>
</project>

Write folder name and their sizes in a file using Ant

I need some help with Ant. I want to create a file using Ant, which to contain some names and the size in kb of some folders and also to contain other kind of data(not size) but with the same pattern.
Something like this:
build.date=April 01, 2000
folder1=10000
folder2=59093
folder3=646854
folder4=14897123
And also to make the sum of some folder sizes(for example foldersum=folder1+folder2) and write that in the file:
build.date=April 01, 2000
folder1=10000
folder2=59093
folder3=646854
folder4=14897123
foldersum=folder1+folder2
ANT is not a programming language. The best way to do this is to embed a scripting language, for example groovy.
Example
Given the following directory structure
├── build.xml
├── folder1
│   ├── file1.txt
│   ├── file2.txt
│   └── file3.txt
├── folder2
│   ├── file4.txt
│   └── file5.txt
└── folder3
└── file6.txt
Produces a file called "build-report.txt"
build.date=April 09,2015
folder1=1
folder2=1
folder3=1
foldersum=3
build.xml
<project name="demo" default="build">
<available classname="org.codehaus.groovy.ant.Groovy" property="groovy.installed"/>
<target name="build" depends="init">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<dirset id="dirs" dir="." includes="folder*"/>
<groovy>
import java.text.SimpleDateFormat
def sdf = new SimpleDateFormat("MMMM dd,yyyy")
new File("build-report.txt").withWriter { w ->
w.println "build.date=${sdf.format(new Date())}"
def total = 0
ant.project.references.dirs.each {
def dir = new File(it.toString())
def size = dir.directorySize()
w.println "${dir.name}=${size}"
total += size
}
w.println "foldersum=${total}"
}
</groovy>
</target>
<target name="init" unless="groovy.installed">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/groovy.jar" src="http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.4.3/groovy-all-2.4.3.jar"/>
<fail message="Groovy installed run build again"/>
</target>
</project>

Map a list of strings to a collection of file resources for a dependset

Background: I read names from an XML file and want to map them to source and target paths for a build task. I am not an experienced Ant user and I'm looking for a way to that is
”readable”
robust and
can be used to determine if targets are out of date (preferably using tasks from Ant or Ant Contrib).
Sample xml:
<list><value>The first name<value><value>The second name</value></list>
Desired resultset:
${dir}/The first name.${ext}
${dir}/The second name.${ext}
I can build the path to each file using pathconvert or mappedresources but I haven't been able to map either result back to a collection of file resources that I can use in a dependset. Is there an elegant solution to this problem?
ANT is not a programming language. Easy to embed groovy.
Example
├── build.xml
├── sample.xml
├── src
│   ├── file1.txt
│   ├── file2.txt
│   └── file3.txt
└── target
├── file1.txt
└── file2.txt
Run as follows
$ ant
Buildfile: /.../build.xml
install-groovy:
build:
[copy] Copying 2 files to /.../target
[copy] Copying /.../src/file1.txt to /.../target/file1.txt
[copy] Copying /.../src/file2.txt to /.../target/file2.txt
BUILD SUCCESSFUL
sample.xml
<list>
<value>file1</value>
<value>file2</value>
</list>
build.xml
<project name="demo" default="build">
<!--
================
Build properties
================
-->
<property name="src.dir" location="src"/>
<property name="src.ext" value="txt"/>
<property name="build.dir" location="target"/>
<available classname="org.codehaus.groovy.ant.Groovy" property="groovy.installed"/>
<!--
===========
Build targets
===========
-->
<target name="build" depends="install-groovy" description="Build the project">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<groovy>
def xmllist = new XmlSlurper().parse(new File("sample.xml"))
ant.copy(todir:properties["build.dir"], verbose:true, overwrite:true) {
fileset(dir:properties["src.dir"]) {
xmllist.value.each {
include(name:"${it}.${properties["src.ext"]}")
}
}
}
</groovy>
</target>
<target name="clean" description="Cleanup project workspace">
<delete dir="${build.dir}"/>
</target>
<target name="install-groovy" description="Install groovy" unless="groovy.installed">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/groovy.jar" src="http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.3.6/groovy-all-2.3.6.jar"/>
<fail message="Groovy has been installed. Run the build again"/>
</target>
</project>

Ant: copy folder and then delete only the files copied

I need a build script to be able to copy a folder with all its nested files and folders to another folder. The destination folder already contains its own files and folders, and its nested folder structure can overlap with the source folder. Having executed some commands, I then need to delete only the files that were copied.
Example:
src_folder
subfolder1
file1
dest_folder
subfolder1
file2
file3
Here I need to delete only dest_folder/subfolder1/file1
Is there a way to do this with Ant? If not, can you suggest an alternative build tool that makes this possible?
One way to accomplish similar results would be to back up dest_folder, but it has a lot of files and it takes too long to copy it.
Example
Project files
├── build.xml
├── dest_folder
│   └── subfolder1
│   ├── file2
│   └── file3
└── src_folder
└── subfolder1
└── file1
Build output
$ ant
Buildfile: build.xml
copy-files:
[copy] Copying 1 file to dest_folder
[copy] Copying src_folder/subfolder1/file1 to dest_folder/subfolder1/file1
run-cmd-on-files-in-dest-folder:
[apply] dest_folder/subfolder1/file1
clean-files:
[delete] Deleting dest_folder/subfolder1/file1
build.xml
<project name="demo" default="run">
<target name="run" depends="copy-files,run-cmd-on-files-in-dest-folder,clean-files"/>
<target name="copy-files">
<copy todir="dest_folder" verbose="true">
<fileset dir="src_folder"/>
</copy>
</target>
<target name="run-cmd-on-files-in-dest-folder">
<apply executable="echo">
<srcfile/>
<fileset dir="dest_folder">
<present present="both" targetdir="src_folder"/>
</fileset>
</apply>
</target>
<target name="clean-files">
<delete verbose="true">
<fileset dir="dest_folder">
<present present="both" targetdir="src_folder"/>
</fileset>
</delete>
</target>
</project>

How to exclude a directory from ant fileset, based on directories contents

How can I create an ant fileset which excludes certain directories based on the contents of the directory?
I use ant to create a distribution jar which has each localization in separate directories, some of which are incomplete and should not be released.
I would like to add something to the directory (for example a file named incomplete.flag) so that ant excludes the directory. Then I can delete the file when translation is complete, and include it in the build without modifying build.xml.
Given this directory structure:
proj
+ locale
+ de-DE
+ en-US
+ fr-FR
This fileset excludes all incompelte.flag files, but how can I exclude the entire directories that contain them?
<fileset dir="${basedir}">
<include name="locale/"/>
<exclude name="locale/*/incomplete.flag">
</fileset>
I can write an ant task if need be, but I'm hoping the fileset can handle this use case.
The following approach works for me:
<exclude name="**/dir_name_to_exclude/**" />
You need to add a '/' after the dir name
<exclude name="WEB-INF/" />
Here's an alternative, instead of adding an incomplete.flag file to every dir you want to exclude, generate a file that contains a listing of all the directories you want to exclude and then use the excludesfile attribute. Something like this:
<fileset dir="${basedir}" excludesfile="FileWithExcludedDirs.properties">
<include name="locale/"/>
<exclude name="locale/*/incomplete.flag">
</fileset>
Hope it helps.
There is actually an example for this type of issue in the Ant documentation. It makes use of
Selectors (mentioned above) and mappers. See last example in http://ant.apache.org/manual/Types/dirset.html :
<dirset id="dirset" dir="${workingdir}">
<present targetdir="${workingdir}">
<mapper type="glob" from="*" to="*/${markerfile}" />
</present>
</dirset>
Selects all directories somewhere under ${workingdir} which contain a ${markerfile}.
Answer provided by user mgaert works for me. I think it should be marked as the right answer.
It works also with complex selectors like in this example:
<!--
selects only direct subdirectories of ${targetdir} if they have a
sub-subdirectory named either sub1 or sub2
-->
<dirset dir="${targetdir}" >
<and>
<depth max="0"/>
<or>
<present targetdir="${targetdir}">
<globmapper from="*" to="*/sub1" />
</present>
<present targetdir="${targetdir}">
<globmapper from="*" to="*/sub2" />
</present>
</or>
</and>
</dirset>
Thus, having a directory structure like this:
targetdir
├── bar
│   └── sub3
├── baz
│   └── sub1
├── foo
│   └── sub2
├── phoo
│   ├── sub1
│   └── sub2
└── qux
└── xyzzy
└── sub1
the above dirset would contain only baz foo phoo (bar doesn't match because of sub3 while xyzzy doesn't match because it's not a direct subdirectory of targetdir)
This is possible by using "**" pattern as following.
<exclude name="maindir/**/incomplete.flag"/>
the above 'exclude' will exclude all directories completely which contains incomplete.flag file.
it works for me with a jar target:
<jar jarfile="${server.jar}" basedir="${classes.dir}" excludes="**/client/">
<manifest>
<attribute name="Main-Class" value="${mainServer.class}" />
</manifest>
</jar>
this code include all files in "classes.dir" but exclude the directory "client" from the jar.
I think one way is first to check whether your file exists and if it exists to exclude the folder from copy:
<target name="excludeLocales">
<property name="de-DE.file" value="${basedir}/locale/de-DE/incompelte.flag"/>
<available property="de-DE.file.exists" file="${de-DE.file}" />
<copy todir="C:/temp/">
<fileset dir="${basedir}/locale">
<exclude name="de-DE/**" if="${de-DE.file.exists}"/>
<include name="xy/**"/>
</fileset>
</copy>
</target>
This should work also for the other languages.
works for me:
<target name="build2-jar" depends="compile" >
<jar destfile="./myJjar.jar">
<fileset dir="./WebContent/WEB-INF/lib" includes="hibernate*.jar,mysql*.jar" />
<fileset dir="./WebContent/WEB-INF/classes" excludes="**/controlador/*.class,**/form/*.class,**/orm/*.class,**/reporting/*.class,**/org/w3/xmldsig/*.class"/>
</jar>

Resources