设置/更改文件的ctime或“更改时间”属性

时间:2013-04-21 01:12:59

标签: java linux ext4 filemtime java.nio.file

我希望使用java.nio.Files类更改Java中文件的时间戳元数据。

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

我可以按如下方式更改前两个时间戳字段:

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

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

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

谢谢!

2 个答案:

答案 0 :(得分:12)

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

  1. 更改内核以使ctimemtime
  2. 匹配
  3. 编写一个简单(但很糟糕)的shell脚本。
  4. 第一种方法:更改内核。

    我在KERNEL_SRC/fs/attr.c中调整了几行。每当mtime“明确定义”时,此修改都会更新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);
    

    以下是KERNEL_SRC/fs/attr.c函数中notify_change的更改:

        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权限。确保在使用之前根据需要修改此脚本。

答案 1 :(得分: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(MSDN上的 GetFileTime 功能)都不容易访问此字段。本机系统调用只能访问创建/访问/修改时间戳,Java也是如此。