10

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

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

我可以更改前两个时间戳字段,如下所示:

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

但是,我无法修改文件上的最后一个更改:时间。此外,令人担忧的是文档中没有提到更改时间戳。最接近的可用属性是creationTime,我尝试过但没有成功。

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

谢谢!

4

2 回答 2

17

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

  1. 更改内核以ctime匹配mtime
  2. 编写一个简单(但很老套)的 shell 脚本。

第一种方法:更改内核。

我在此修改中只调整了几行,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 设置为该值。

第二种方法:简单(但 hacky)的 shell 脚本。

简要说明:

  1. 将系统时间更改为您的目标时间
  2. 对文件执行 chmod,文件 ctime 现在反映目标时间
  3. 恢复系统时间。

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

于 2013-06-12T13:05:49.907 回答
3

根据您的情况调整此答案

// 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(man touch)和 Windows( MSDN 上的GetFileTime函数)都不能轻松访问该字段。本机系统调用仅提供对创建/访问/修改时间戳的访问权限,Java 也是如此。

于 2013-04-21T02:48:29.910 回答