linux下文件时间戳修改

时间:2021-11-13 02:18:22

1.touch命令
linux的touch命令不常用,一般在使用make的时候可能会用到,用来修改文件时间戳,或者新建一个不存在的文件。
命令格式:
touch [选项]… 文件…
命令参数:
-a 或–time=atime或–time=access或–time=use  只更改存取时间。
-c 或–no-create  不建立任何文档。
-d  使用指定的日期时间,而非现在的时间。
-f  此参数将忽略不予处理,仅负责解决BSD版本touch指令的兼容性问题。
-m 或–time=mtime或–time=modify  只更改变动时间。
-r  把指定文档或目录的日期时间,统统设成和参考文档或目录的日期时间相同。
-t  使用指定的日期时间,而非现在的时间。

2.
一个文件的访问和修改时间可以用以下几个函数更改。futimens和utimensat函数可以指定纳秒级精度的时间戳。用到的数据结构是与stat函数族相同的timespec结构(见4.2节)。

#include <sys/stat.h> 

int futimens(int fd, const struct timespec times[2]);

int utimensat(int fd, const char *path, const struct timespec times[2], int flag);

两个函数返回值:若成功,返回0;若出错,返回-1
这两个函数的times数组参数的第一个元素包含访问时间,第二元素包含修改时间。这两个时间值是日历时间,如1.10节所述,这是自特定时间(1970年1月1日00:00:00)以来所经过的秒数。不足秒的部分用纳秒表示。

时间戳可以按下列4种方式之一进行指定。

(1)如果times参数是一个空指针,则访问时间和修改时间两者都设置为当前时间
(2)如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_NOW,相应的时间戳就设置为当前时间,忽略相应的tv_sec字段。
(3)如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_OMIT,相应的时间戳保持不变,忽略相应的tv_sec字段。
(4)如果times参数指向两个timespec结构的数组,且tv_nsec字段的值为既不是UTIME_NOW也不是UTIME_OMIT,在这种情况下,相应的时间戳设置为相应的tv_sec和tv_nsec字段的值。

执行这些函数所要求的优先权取决于times参数的值。

如果times是一个空指针,或者任一tv_nsec字段设为UTIME_NOW,则进程的有效用户ID必须等于该文件的所有者ID;进程对该文件必须具有写权限,或者进程是一个超级用户进程。

如果times是非空指针,并且任一tv_nsec字段的值既不是UTIME_NOW也不是UTIME_OMIT,则进程的有效用户ID必须等于该文件的所有者ID,或者进程必须是一个超级用户进程。对文件只具有写权限是不够的。

如果times是非空指针,并且两个tv_nsec字段的值都为UTIME_OMIT,就不执行任何的权限检查。

futimens函数需要打开文件来更改它的时间,utimensat函数提供了一种使用文件名更改文件时间的方法。pathname参数是相对于fd参数进行计算的,fd要么是打开目录的文件描述符,要么设置为特殊值AT_FDCWD(强制通过相对于调用进程的当前目录计算pathname)。如果pathname指定了绝对路径,那么fd参数被忽略。

utimensat的flag参数可用于进一步修改默认行为。如果设置了AT_SYMLINK_NOFOLLOW标志,则符号链接本身的时间就会被修改(如果路径名指向符号链接)。默认的行为是跟随符号链接,并把文件的时间改成符号链接的时间。

futimens和utimensat函数都包含在POSIX.1中,第3个函数utimes包含在Single UNIX Specification的XSI扩展选项中。

#include <sys/time.h> 

int utimes(const char *pathname, const struct timeval times[2]);

函数返回值:若成功,返回0;若出错,返回-1
utimes函数对路径名进行操作。times参数是指向包含两个时间戳(访问时间和修改时间)元素的数组的指针,两个时间戳是用秒和微妙表示的。


struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};

注意,我们不能对状态更改时间st_ctim(i节点最近被修改的时间)指定一个值,因为调用utimes函数时,此字段会被自动更新。

在某些UNIX版本中,touch(1)命令使用这些函数中的某一个。另外,标准归档程序tar(1)和cpio(1)可选地调用这些函数,以便将一个文件的时间值设置为将它归档时保存的时间。

程序使用带O_TRUNC选项的open函数将文件长度截断为0,但并不更改其访问时间及修改时间。为了做到这一点,首先用stat函数得到这些时间,然后截断文件,最后再用futimens函数重置这两个时间。linux下文件时间戳修改
可以用以下Linux命令演示图4-21中的程序:


$ ls -l changemod times 查看长度和最后修改时间
-rwxr-xr-x 1 sar 13792 Jan 22 01:26 changemod
-rwxr-xr-x 1 sar 13824 Jan 22 01:26 times
$ ls -lu changemod times 查看最后访问时间
-rwxr-xr-x 1 sar 13792 Jan 22 22:22 changemod
-rwxr-xr-x 1 sar 13824 Jan 22 22:22 times
$ date 打印当天日期
Fri Jan 27 20:53:46 EST 2012
$ ./a.out changemod times 运行图4-21的程序
$ ls -l changemod times 检查结果
-rwxr-xr-x 1 sar 0 Jan 22 01:26 changemod
-rwxr-xr-x 1 sar 0 Jan 22 01:26 times
$ ls -lu changemod times 检查最后访问时间
-rwxr-xr-x 1 sar 0 Jan 22 22:22 changemod
-rwxr-xr-x 1 sar 0 Jan 22 22:22 times
$ ls -lc changemod times 检查状态更改时间
-rwxr-xr-x 1 sar 0 Jan 27 20:53 changemod
-rwxr-xr-x 1 sar 0 Jan 27 20:53 times

正如我们所预见的一样,最后修改时间和最后访问时间未变。但是,状态更改时间则更改为程序运行时的时间。