I am writing a manifest.xml
file during an Ant build for an OpenCMS project.
I need to be able to pull up a file's create date, and last modified date on a file. (Although the current process is giving each file a timestamp of Wed, 31 Dec 1969 19:00:00 EST
anyway -- at least on Windows machines when they run the build.)
Is there a way I can pull up the creation date timestamp of a file in Ant? I'm using standard Ant tasks and Ant-Contrib tasks.
It depends on your OS, f.e. Unix doesn't store the file creation time, see details here
Two possible solutions :
Solution 1, works on Windows only with Java >= 6, no addons needed
<project>
<!-- Works on Windows only, uses the jdk builtin
rhino javascript engine (since jdk6)
use dir command without /T:C to get lastmodificationtime
-->
<macrodef name="getFileTimes">
<attribute name="dir" />
<attribute name="file" />
<attribute name="setprop" default="@{file}_ctime" />
<sequential>
<exec executable="cmd" dir="@{dir}" outputproperty="@{setprop}">
<arg value="/c" />
<arg line="dir @{file} /T:C|find ' @{file}'" />
</exec>
<script language="javascript">
tmp = project.getProperty("@{setprop}").split("\\s+") ;
project.setProperty("@{setprop}", tmp[0] + "/" + tmp[1]) ;
</script>
</sequential>
</macrodef>
<getFileTimes dir="C:/tmp" file="bookmarks.html" />
<echo>
$${bookmarks.html_ctime} => ${bookmarks.html_ctime}
</echo>
</project>
Solution 2, needs Java 7 and groovy-all-x.x.x.jar (contained in groovy binary release)
Adjust the SimpleDateFormat to your liking.
On Unix filesystems when asking for creationtime you'll get the last modification time.
<project>
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<!-- Solution for Java 7, uses the nio package
needs groovy-all-2.1.0.jar
-->
<macrodef name="getFileTimes">
<attribute name="file"/>
<attribute name="ctimeprop" default="@{file}_ctime"/>
<attribute name="mtimeprop" default="@{file}_mtime"/>
<sequential>
<groovy>
import java.nio.file.*
import java.nio.file.attribute.*
import java.text.*
import java.util.date.*
Path path = Paths.get("@{file}")
BasicFileAttributeView view = Files.getFileAttributeView(path, BasicFileAttributeView.class)
BasicFileAttributes attributes = view.readAttributes()
lastModifiedTime = attributes.lastModifiedTime()
createTime = attributes.creationTime()
DateFormat df = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.US)
df.format(new Date(createTime.toMillis()))
properties.'@{ctimeprop}' = df.format(new Date(createTime.toMillis()))
properties.'@{mtimeprop}' = df.format(new Date(lastModifiedTime.toMillis()))
</groovy>
</sequential>
</macrodef>
<getFileTimes file="C:/tmp/bookmarks.html"/>
<echo>
$${C:/tmp/bookmarks.html_ctime} => ${C:/tmp/bookmarks.html_ctime}
$${C:/tmp/bookmarks.html_mtime} => ${C:/tmp/bookmarks.html_mtime}
</echo>
</project>
I tried also using the builtin javascript engine, but i got errors like :
sun.org.mozilla.javascript.internal.EvaluatorException: missing name after . operator
IMO, for simple things using javascript <script language="javascript">
is sufficient, but if you need to import java packages etc. .. it's a PITA. Groovy simply works.
I've got this to work.
As Mark O'Connor pointed out, you can't get the file creation time from earlier versions of Java. However, the original Java program that was being used for this task used the lastModified method for both the creation date and the last modified date1. I was fine doing the same thing.
I created a <scriptdef>
to do pull the Last Modified date from a file. In Java 1.6 and up, you have access directly to the Rhino JavaScript library, so you no longer need the BeanShell library.
<scriptdef name="file.mdate" language="javascript">
<attribute name="file"/>
<attribute name="property"/>
file_name = attributes.get("file");
property_to_set = attributes.get("property");
file = new java.io.File(file_name);
file_date = file.lastModified();
date_format = new java.text.SimpleDateFormat("EEE, dd MMM YYYY HH:mm:ss zzz");
formated_date = date_format.format(new java.util.Date(file_date));
project.setNewProperty(property_to_set, formated_date);
</scriptdef>
Once defined, I can use it as an Ant task:
<file.mdate
file="${file.name}"
property="file.modified.date"/>
<echo>The file "${file}" was modified on ${file.modified.date}</echo>
Problem is the standard Java File object only supports a method for returning the last modified date:
- How to discover a File's creation time with Java?
- Determine file creation date in Java
The problem is addressed in Java 7, using the new NIO classes:
- http://docs.oracle.com/javase/tutorial/essential/io/fileAttr.html
Obviously to take advantage of this in ANT you'd need to write a custom task or embed a script.
There was a bug in David W.s answer:
it not works on second run, because the attribute is not overwritten on second run.
Change: project.setNewProperty
should be project.setProperty
Full code snippet:
<scriptdef name="filedate" language="javascript">
<attribute name="file"/>
<attribute name="property"/>
<![CDATA[
file_name = attributes.get("file");
property_to_set = attributes.get("property");
file = new java.io.File(file_name);
file_date = file.lastModified();
date_format = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
formated_date = date_format.format(new java.util.Date(file_date));
project.setProperty(property_to_set, formated_date);
]]>
</scriptdef>