Archive files using Ant from Groovy

Load the JSON config, then use the Groovy AntBuilder to iterate a fileset, repeatably calling the zip Ant task.

In Ant The zip task takes a fileset but only creates one archive. How do you zip files into individual archives?

Use case
One use case for this is log files. Sooner rather then later, every system must deal with the growth of log files. One of the best utilities for handling this is logrotate. This is available on *nix systems. There are probably native versions that do similar tasks in Windows, but I did not locate any ‘free as in beer’ ones.

Since I’m working with Ant, on Windoze, and can’t install cygwin or other system, will use Groovy to get around Ant limitations. This will not be an attempt to recreate logrotate, of course.

As in a previous post, we can use the Groovy AntBuilder and iterate a fileset to repeatably call an Ant task. In this case we’ll be invoking the zip task. Note that the same approach could be used to create a scriptdef to do this directly in an Ant build script. This would be more usable since we could declaratively define the fileset, etc.


First the configuration. In listing 1, we use a JSON configuration file. No reason, I’m just tired of Property files.

Listing 1, JSON configuration file

{ "about":

In listing 2, the main entry point calls the config loader and then the ‘archiveLogs’ method.

The fileset created with the AntBuilder uses an Ant ‘date’ selector to find the files that are x amount of days old. Then the resulting fileset is scanned in a loop, invoking the zip task as we go and then deleting the just zipped file. It is assumed here that the target file name has descriptive information, like a date. And, we are not adding a “rotate” counter to the name for future logrotate like behavior.

Listing 2, Groovy archive source

package ant

import java.text.*
import groovy.json.JsonSlurper

 * @author jbetancourt
class ArchiveLogs {
	def format = "yyMMdd'T'kkmm"
	def df = new SimpleDateFormat(format)

	/** entry point */
	static main(args) {
		def als = new ArchiveLogs()	
		def p = (
		  (args) ?
		  args[0] : "test/conf/archivelogs.json")
		def map = als.loadConfiguration(p)

	/**  */
	def archiveLogs(conf) {
		def base = conf.base
		def targetDateString = df.format(
			(new Date() - Integer.parseInt(conf.days))
		def ant = new AntBuilder()		
		def ref = ant.project.getReference(
		ref.each{ fileResource ->
			File file = fileResource.getFile()
			def name = file.getName()
	/** load json file */
	def loadConfiguration(String path){
		def slurper = new JsonSlurper()
		def obj = slurper.parse(
			 new File(path).newReader())
		if(obj.config.debug == 'true'){
				println it
		return obj.config

This is, of course, a simplistic approach. For example, what if the file is being used when we attempt to delete it? Or we fail to zip the file, but continue to delete it? And, this source, being an example, does not have any error handling.

The ant-contribs project has looping support, foreach. Directly using the Java util packages for archiving, such as Or, the libraries found in, for example, the Apache commons project.

Further Reading

“cafe”, egberto gismonti

Leave a Reply

Your email address will not be published. Required fields are marked *