ANT How to delete ONLY empty directories recursively - ant

Does anyone know how to recursively delete "empty" directories with ANT (empty includes directories that only contain ".svn" etc).
I know ant allows you to "includeEmptyDirs=true" but I want it to ONLY delete a directory if it is empty (and actually I'd probably need to walk up the recursive chain and delete the directory it was contained in if it is now empty).
Basically as part of our build process we copy over a set of directories that contain a bunch of other nested directories containing various XML and data, and when we move the location for that data our "copy" and checkin build process doesn't really work, and because we are checking into another source control (SVN), wiping out the directories and copying over isn't really an option either (we'd be blowing away the ".svn" folders).
Before we copy over the new builds I can "clear" out the directories by doing the following:
<delete>
<fileset dir="${webplatformBin}" includes="**/*"/>
</delete>
This leaves every directory (with the ".svn") as an empty directory and then I copy over the new files. After they're copied I'm not sure how I can clear out the empty directories that are left (if we've completely moved where the top-level data directory is etc.).
For example if I had a /projectA/data/localization/text.xml file and I moved it to /projectB/data/localization/text.xml, I would end up with an empty folder /projectA/data/localization/ (that would only contain a .svn folder).

Here's the best answer I've been able to come up with:
<delete includeemptydirs="true">
<fileset dir="${dirToStartFrom}" >
<and>
<size value="0"/>
<type type="dir"/>
</and>
</fileset>
</delete>
I then wrapped it in a macro so I can pass the dir name in from any target:
<!-- Find and delete empty folders under dir -->
<macrodef name="deleteEmptyFolders">
<attribute name="dir"/>
<sequential>
<delete includeemptydirs="true">
<fileset dir="#{dir}" >
<and>
<size value="0"/>
<type type="dir"/>
</and>
</fileset>
</delete>
</sequential>
</macrodef>
Like so:
<target name="clean">
<deleteEmptyFolders dir="build"/>
<deleteEmptyFolders dir="common"/>
<deleteEmptyFolders dir="lib"/>
</target>

Here's what I cooked up:
<!-- next three targets are connected
To remove empty folders from XXX folder. Process is recursed 3 times. This
is necessary because parent directories are not removed until all their children
are (if they are empty), and parents are processed before children
My example will process structures 3 deep, if you need to go deeper
then add members to the list like list="1,2,3,x,x,x,x,x,x" -->
<target name="rmmtdirs">
<foreach list="1,2,3" target="rmmtdirs_recurse" param="num"/>
</target>
<target name="rmmtdirs_recurse">
<foreach target="rmmtdir" param="rmdir">
<path>
<dirset dir="${XXX}"/>
</path>
</foreach>
</target>
<target name="rmmtdir">
<echo message=" Removing: ${rmdir} "/>
<delete includeemptydirs="true">
<fileset dir="${rmdir}" excludes="**/*"/>
</delete>
</target>

I was able to delete all the empty directories starting with the current working directory with the following:
<delete includeemptydirs="true">
<fileset dir="." includes="**" excludes="**/*.*" />
</delete>

If it is not sufficient to completely clear the target location (use defaultExcludes="false" to ensure the .svn folders are deleted), you could try writing a custom ant task to traverse the file system below the target, deleting empty directories as you move back up from each leaf.

This is probably easier to do with a batch file that gets called from ant.
You can use Raymond Chen's script, but it doesn't work if there are spaces in the names.

Related

Delete a folder using starts with in ANT

I am comparing 2 folders A and B, and wanted to delete folders and jars present in B which are not present in folder A.
I have written the logic to get needed files to delete, but i do not wanted to delete the directory and jars starting with "com.ibm".
For that I have written delete task as below:
<delete>
<dirset dir="D://mypath/plugins<Filename to delete> excludes="**/com.ibm.*/**" />
</delete>
I have tried the excludes with the scenarios like:
excludes="**/com.ibm.*/**"
excludes="**/com.ibm.*"
excludes="com.ibm.*"
excludes="com.ibm.*/**"
But nothing works for me (It is not deleting any folders/files). Any help would be highly appreciated. Thanks !
you should use fileset instead and specify includeemptydirs="true" of delete.
<project default="init" name="My Project">
<target name="init">
<delete verbose="true" includeemptydirs="true">
<fileset dir="/home/guest/Desktop/plugins" defaultexcludes="no">
<exclude name="com.ibm.*"/>
<exclude name="com.ibm.*/**"/>
</fileset>
</delete>
</target>
</project>

No overwrite on Ant UNZIP

I want to unzip a file, but if some file exists, this mustn´t be replaced.
I tried this:
<unzip src="compress.zip" dest="dirTo" overwrite="false">
<patternset>
<include name="dirFrom/**"/>
</patternset>
"dirFrom", is the name from the directory IN the compress file, what I want to extract. I use "overwrite" to false, but it doesn´t work, and it ovewrites.
I have a directory, and this has different subdirectories. I want one of those subdirectories, with it´s files and sub-subdirectories.
I found how to do it.
1st, I extract everything to auxiliar directory.
2nd, I make a loop, to compare file by file, if that file exists.
3rd, If the file doesn´t exists, I copy it.
<unzip src="compressFile.zip" dest="dirAux">
<patternset>
<include name="mySubDir/**"/>
</patternset>
</unzip>
<fileset id="fileset1" dir="dirAux/mySubDir" />
<property name="newContentMySubDir" refid="fileset1"/>
<for param="nameFile" list="${newContentMySubDir}" delimiter=";">
<sequential>
<if>
<not><available file="${finalDir}/mySubDir/#{nameFile}" type="file"/></not>
<then>
<copy tofile="${finalDir}/mySubDir/#{nameFile}" file="dirAux/mySubDir/#{nameFile}"/>
</then>
</if>
</sequential>
</for>
Setting overwrite to false will only prevent to overwrite destination file if it is newer than source file. For more complex filtering, you have to use copy task with a zipfilset as it is explain in ant documentation (see unzip task -- in section Related tasks). For exemple, following code should not extract files from a zip file if they already exist in the destination directory (respecting source directories layout):
<copy todir="${target.dir}">
<zipfileset src="${zip.file}">
<patternset>
<include name="**/*.*"/>
</patternset>
<present targetdir="${target.dir}" present="srconly"/>
</zipfileset>
</copy>

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

How do I build an Ant TarTask for this tar command?

tar zcvf Test.tar.gz /var/trac/test /var/svn/test
So far I have:
<target name="archive" depends="init">
<tar compression="gzip" destfile="test.tar.gz">
<tarfileset dir="/">
<include name="/var/trac/test" />
</tarfileset>
<tarfileset dir="/">
<include name="/var/trac/svn" />
</tarfileset>
</tar>
</target>
With debugging on, it always says "No sources found" so I'm a bit perplexed on what to do next.
There are several things here that can go wrong:
Are /var/trac/test and /var/svn/test files or directories? Real tar would work fine with both; your task - the way it's written right now - would only work with files but not folders.
Do you (or, rather, does Ant process) have adequate permissions?
<include> elements contain patterns, which are generally relative to base dir. You're specifying them as absolute.
I would rewrite the above as:
<target name="archive" depends="init">
<tar compression="gzip" destfile="test.tar.gz">
<tarfileset dir="/var/trac" prefix="/var/trac">
<include name="test/**" />
<include name="svn/**" />
</tarfileset>
</tar>
</target>
prefix allows you to explicitly specify the path with which files in Tar archive should begin.
/** within <include> tells Ant to take all the files from that folder and all its subfolders. If /var/trac/test and /var/svn/test are indeed files and not folders then you can omit that.

Resources