2013-04-21 126 views
6

我希望使用java.nio.Files类更改Java文件中的时间戳记元数据。设置/更改文件的ctime或“更改时间”属性

我想更改所有3个Linux/ext4时间戳(上次修改,访问和更改)。

我能够改变前两个时间戳字段如下:

Files.setLastModifiedTime(pathToMyFile, myCustomTime); 
Files.setAttribute(pathToMyFile, "basic:lastAccessTime", myCustomTime); 

但是,我无法改变最后变化:时间上的文件。另外,关于documentation中提到的没有更改时间戳。最接近的可用属性是creationTime,我尝试过没有任何成功。

有关如何根据Java中的自定义时间戳修改文件的Change:元数据的任何想法?

谢谢!

+0

在Linux终端中,对于ls输出,它显示上次修改时间,您是否尝试修改它? – 2013-04-21 01:52:17

+0

是的。我使用上面的第一行代码成功修改了上次修改的时间。 – Eitan 2013-04-21 07:41:17

回答

10

我能够用两种不同的方法来修改的ctime:

  1. 改变内核,使ctime匹配mtime
  2. 编写一个简单的(但哈克)shell脚本。

第一种方法:更改内核。

我调整了几行KERNEL_SRC/fs/attr.c此修改更新ctime以匹配mtime,只要mtime是“明确定义的”。

有很多种方法,以 “明确定义” 的的修改时间,例如:

在Linux中:

touch -m --date="Wed Jun 12 14:00:00 IDT 2013" filename 

在Java(使用Java 6或7的,想必其他人):

long newModificationTime = TIME_IN_MILLIS_SINCE_EPOCH; 
File myFile = new File(myPath); 
newmeta.setLastModified(newModificationTime); 

这里是在notify_change功能的变化KERNEL_SRC/fs/attr.c

now = current_fs_time(inode->i_sb); 

    //attr->ia_ctime = now; (1) Comment this out 
    if (!(ia_valid & ATTR_ATIME_SET)) 
     attr->ia_atime = now; 
    if (!(ia_valid & ATTR_MTIME_SET)) { 
     attr->ia_mtime = now; 
    } 
    else { //mtime is modified to a specific time. (2) Add these lines 
     attr->ia_ctime = attr->ia_mtime; //Sets the ctime 
     attr->ia_atime = attr->ia_mtime; //Sets the atime (optional) 
    } 

(1)此行未注释,会在更改文件时将ctime更新为当前时钟时间。我们不希望这样,因为我们想自己设置ctime。因此,我们评论这条线。 (这不是强制性的)

(2)这实际上是解决方案的关键。notify_change函数在文件更改后执行,其中时间元数据需要更新。如果未指定mtime,则将mtime设置为当前时间。否则,如果mtime设置为特定值,我们也将ctime和atime设置为该值。

第二种方法:简单(但哈克)shell脚本。

简要说明: 1)更改系统时间到你的目标时间 2)对文件执行在chmod,文件的ctime现在反映目标时间 3)还原系统时间回来。

changectime.sh

#!/bin/sh 
now=$(date) 
echo $now 
sudo date --set="Sat May 11 06:00:00 IDT 2013" 
chmod 777 $1 
sudo date --set="$now" 

运行此如下: ./changectime.sh MYFILE

该文件的的ctime现在将反映在文件中的时间。

当然,你可能不想拥有777权限的文件。确保您在使用该脚本之前根据需要修改此脚本。

+0

需要更改脚本。现在= $(日期)不会(总是)获取有效的日期格式进行设置。使用:now = $(日期+“%Y-%M-%d%T”)。那个脚本/方法很整洁,对我很有用。 – gaoithe 2016-05-25 10:10:32

2

适应this answer到您的情况:

// Warning: Disk must be unmounted before this operation 
String disk = "/dev/sda1"; 
// Update ctime 
Runtime.getRuntime().exec("debugfs -w -R 'set_inode_field "+pathToMyFile+" ctime "+myCustomTime+"' "+disk); 
// Drop vm cache so ctime update is reflected 
Runtime.getRuntime().exec("echo 2 > /proc/sys/vm/drop_caches"); 

我怀疑我们将看到在标准的Java API一个方便的方法来做到这一点,因为无论Linux操作系统(男子触摸)也不支持Windows(GetFileTime功能上MSDN)可以轻松访问此字段。本地系统调用只能访问创建/访问/修改时间戳,Java也是如此。

+0

有没有其他方法可以让我保持磁盘安装? – Eitan 2013-04-21 07:42:51