10

java.nio.Filesクラスを使用して Java のファイルのタイムスタンプ メタデータを変更したいと考えています。

3 つの Linux/ext4 タイムスタンプ (最終変更、アクセス、および変更) をすべて変更したいと考えています。

最初の 2 つのタイムスタンプ フィールドを次のように変更できます。

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

ただし、ファイルの最後の変更:時刻を変更できません。また、ドキュメントに記載されている変更タイムスタンプがないことも懸念されます。最も近い利用可能な属性はcreationTimeで、これを試しても成功しませんでした。

Change:Java のカスタム タイムスタンプに従ってファイルのメタデータを変更する方法についてのアイデアはありますか?

ありがとうございました!

4

2 に答える 2

17

2 つの異なる方法で ctime を変更できました。

  1. ctime一致するようにカーネルを変更するmtime
  2. 単純な (しかしハックな) シェル スクリプトを作成します。

第 1 の方法: カーネルを変更します。

この変更により、mtime が「明示的に定義されているKERNEL_SRC/fs/attr.c 」場合は常に mtime と一致するように ctime が更新されます。

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 もその値に設定します。

2 番目の方法: シンプルな (しかしハッキーな) シェル スクリプト。

簡単な説明:

  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 のファイルは必要ないでしょう。このスクリプトを使用する前に、必要に応じて変更してください。

于 2013-06-12T13:05:49.907 に答える
3

Adapting this answer to your case:

// 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");

I doubt we will see a convenient method in Standard Java API to do this, as neither Linux (man touch) nor Windows (GetFileTime function on MSDN) give easy access to this field. Native system calls give only access to creation/access/modify timestamps, so does Java.

于 2013-04-21T02:48:29.910 に答える