2013-04-21 30 views
6

Tôi muốn thay đổi siêu dữ liệu dấu thời gian trên các tệp trong Java bằng cách sử dụng lớp java.nio.Files.Cài đặt/thay đổi thuộc tính ctime hoặc "Thay đổi thời gian" trên một tệp

Tôi muốn thay đổi tất cả 3 dấu thời gian Linux/ext4 (sửa đổi lần cuối, quyền truy cập và thay đổi).

tôi có thể thay đổi hai lĩnh vực timestamp đầu tiên như sau:

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

Tuy nhiên, tôi không thể thay đổi Thay đổi lần cuối: thời gian trên các tập tin. Ngoài ra, nó liên quan đến việc không có dấu thời gian thay đổi được đề cập trong documentation. Thuộc tính có sẵn gần nhất là creationTime, mà tôi đã thử mà không thành công.

Bất kỳ ý tưởng nào về cách sửa đổi siêu dữ liệu Change: cho tệp theo dấu thời gian tùy chỉnh trong Java?

Cảm ơn bạn!

+0

Trong thiết bị đầu cuối Linux, cho đầu ra ls, nó hiển thị thời gian sửa đổi lần cuối, bạn có thử sửa đổi điều đó không? –

+0

Có. Tôi đã sửa đổi thành công lần sửa đổi lần cuối bằng cách sử dụng dòng mã đầu tiên ở trên. – Eitan

Trả lời

10

tôi đã có thể thay đổi ctime với hai phương pháp khác nhau:

  1. Thay đổi hạt nhân để ctime phù hợp với mtime
  2. Viết một kịch bản đơn giản (nhưng hacky).

Phương pháp thứ nhất: Thay đổi hạt nhân.

Tôi đã tinh chỉnh chỉ một vài dòng trong KERNEL_SRC/fs/attr.c Sửa đổi này cập nhật thời gian để phù hợp với thời gian đó bất cứ khi nào mtime được "xác định rõ ràng".

Có rất nhiều cách để "xác định một cách rõ ràng" các sự mtime, ví dụ:

Trong Linux:

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

Trong Java (sử dụng Java 6 hoặc 7, và có lẽ những người khác):

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

đây là sự thay đổi để KERNEL_SRC/fs/attr.c trong notify_change chức năng:

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) Dòng này, không được chú trọng, sẽ cập nhật thời gian ctime thành thời gian đồng hồ hiện tại khi có thay đổi đối với tệp. Chúng tôi không muốn điều đó, vì chúng tôi muốn tự mình đặt thời gian. Vì vậy, chúng tôi bình luận dòng này ra. (Điều này không bắt buộc)

(2) Đây thực sự là mấu chốt của giải pháp.Hàm notify_change được thực thi sau khi một tệp đã được thay đổi, trong đó siêu dữ liệu thời gian cần được cập nhật. Nếu không có mtime nào được chỉ định, thì mtime được đặt thành thời gian hiện tại. Khác, nếu mtime được đặt thành một giá trị cụ thể, chúng tôi cũng đặt ctime và atime thành giá trị đó.

Phương pháp thứ hai: Kịch bản lệnh shell đơn giản (nhưng hack).

giải thích tóm tắt: 1) Thay đổi thời gian hệ thống thời gian mục tiêu của bạn 2) Thực hiện một chmod vào file, file ctime nay phản ánh thời gian mục tiêu 3) Hoàn nguyên thời gian hệ thống lại.

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" 

Run này như sau: myfile ./changectime.sh

ctime của tập tin bây giờ sẽ phản ánh thời gian trong file.

Tất nhiên, có thể bạn không muốn tệp có 777 quyền. Đảm bảo rằng bạn sửa đổi kịch bản này theo nhu cầu của bạn trước khi sử dụng nó.

+0

Cần thay đổi tập lệnh. now = $ (ngày) không (luôn luôn?) có định dạng ngày hợp lệ để cài đặt. Sử dụng: now = $ (date + "% Y-% M-% d% T"). Đó là kịch bản/phương pháp gọn gàng và nó hoạt động cho tôi. – gaoithe

2

Thích ứng this answer đến trường hợp của bạn:

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

tôi nghi ngờ chúng ta sẽ thấy một phương pháp thuận tiện trong tiêu chuẩn Java API để làm điều này, như không phải Linux (người đàn ông lạc) hay Windows (GetFileTime chức năng trên MSDN) cho phép truy cập dễ dàng vào trường này. Các cuộc gọi hệ thống riêng chỉ cấp quyền truy cập vào các dấu thời gian tạo/truy cập/sửa đổi, do đó, Java cũng vậy.

+0

Có cách nào thay thế cho phép tôi giữ đĩa được lắp không? – Eitan

Các vấn đề liên quan