文件的时间

引言 



ls(1)命令按照文件的时间排序可以参考如下选项:



  • 系统默认(用-l或者-t)是按照文件的修改时间的先后排序
  • -u选项按访问时间排序
  • -c选项按状态更改时间排序



stat结构体下面的3个时间值中的一个排序。


1. struct stat 
2. {
3. mode_t st_mode;/* file type & mode (permissions) */
4. ino_t st_ino;/* i-node number (serial number) */
5. dev_t st_dev;/* device number (file system) */
6. dev_t st_rdev;/* device number for special files */
7. nlink_t st_nlink;/* number of links */
8. uid_t st_uid;/* user ID of owner */
9. gid_t st_gid;/* group ID of owner */
10. off_t st_size;/* size in bytes, for regular files */
11. struct timespec st_atim;/* time of last access */
12. struct timespec st_mtim;/* time of last modification */
13. struct timespec st_ctim;/* time of last file status change */
14. blksize_t st_blksize;/* best I/O block size */
15. blkcnt_t st_blocks;/* number of disk blocks allocated */
16. };



stat结构中的大多数成员都是基本系统数据类型。



timespec结构类型如下,其定义在 linux/time.h :


1. struct timespec {
2. time_t tv_sec;/* seconds */
3. long tv_nsec;/* nanoseconds */
4. };



    在2008年版以前的标准中,时间字段定义成 st_atimest_mtime以及 st_ctime,它们都是 time_t类型(以秒来表示)。 而之后 timespec 结构提供了更精度的时间戳。为了保持兼容性,旧的名字可以定义成 tv_sec 成员。 例如, st_atime 可以定义成st_atim.tv_sev。(注意少了一个e字母)



Field

Description

Example

ls(1) option

st_atim

last-access time of file data

read

-u

st_mtim

last-modification time of file data

write

默认

st_ctim

last-change time of i-node status

chmod、chown

-c



表1 与每个文件相关的3个时间值



st_mtim)是文件内容最后一次被修改的时间。



st_ctim)是该文件的i节点最后一次被修改的时间。



   



函数futimens、utimensat和utimes



futimensutimensat函数可以指定纳秒级精度的时间戳。


#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); 
Both return: 0 if OK, −1 on error


    times数组参数的第一个元素包含访问时间,第二个元素包含修改时间。这两个时间值是日历时间。该值是自协调世界(Coordinated Universal Time, UTC)1970年1月1日00:00:00这个特定的时间以来所经过的秒数累计值。早期的手册称UTC为格林尼治标准时间。



    futimensutimensat函数都包含在POSIX.1中,而下面的 utimes函数是在Single UNIX Specification的XSI扩展选项中。


#include <sys/time.h> 
int utimes(const char *pathname, const struct timeval times[2]); 
Returns: 0 if OK, −1 on error


utimes 函数对路径名进行操作。times参数指向包含两个时间戳(访问时间和修改时间)元素的数组,两个时间戳是用秒和微妙表示的。

1. struct timeval {
2. time_t tv_sec;/* seconds */
3. long tv_usec;/* microseconds */
4. };


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



    在某些UNIX版本中, touch(1)命令使用这些函数中的某一个。



实例



    使用带 O_TRUNC选项的 open函数将文件长度截断为0,但并不更改其访问时间。为了做到这点,首先使用 stat函数得到这些时间,然后截断文件,最后再用 futimens函数重置这两个时间。



 


1. /**
2.  * 文件内容:使用带O_TRUNC选项的open函数将文件长度截断为0,但并不更改其访问时间
3.  * 作者:firewaywei@126.com
4.  * 时间:2016年 11月 04日 星期五 22:00:14 CST
5.  */
6. #include<stdio.h>
7. #include<stdlib.h>
8. #include<string.h>
9. #include<errno.h>
10. #include<sys/types.h>
11. #include<sys/stat.h>
12. #include<unistd.h>
13. #include<fcntl.h>
14. 
15. int main(int argc,char*argv[])
16. {
17. int fd =0;
18. struct stat statbuf;
19. struct timespec times[2];
20. int i =0;
21. for(i =1; i < argc; i++)
22. {
23. if(stat(argv[i],&statbuf)<0)
24. {
25.  printf("%s: stat error: %s\n", argv[1], strerror(errno));
26. continue;
27. }
28. 
29. if(fd = open(argv[i], O_RDWR | O_TRUNC)<0)
30. {
31.  printf("%s: open error: %s\n", argv[1], strerror(errno));
32. continue;
33. }
34. 
35.  times[0]= statbuf.st_atim;
36.  times[1]= statbuf.st_mtim;
37. if(futimens(fd, times)<0)
38. {
39.  printf("%s: futimens error: %s\n", argv[1], strerror(errno));
40. }
41. 
42. if(fd >0)
43. {
44.  close(fd);
45. }
46. }
47. 
48.  exit(0);
49. }


代码1 futimens函数实例



    程序运行如下:



ls -l test test.c     
       <------------ 查看长度和最后修改时间 
       
-rwxrwxr-x 1 fireway fireway 9813  8月 14 18:14 test 
       
-rw-rw-r-- 1 fireway fireway  475  8月 14 18:04 test.c 
       
$ 
       ls -lu test test.c     
       <-------------查看最后访问时间 
       
-rwxrwxr-x 1 fireway fireway 9813  8月 14 18:14 test 
       
-rw-rw-r-- 1 fireway fireway  475  9月  9 22:44 test.c 
       
$ 
       date   
        <---------------打印当天日期 
       
2016年 11月 03日 星期四 07:54:21 CST 
       
$ 
       a.out test test.c     
       <----------运行上面的程序 
       
$ 
       ls -l test test.c     
       <--------------检查结果 
       
-rwxrwxr-x 1 fireway fireway 0 11月  3 07:55 test 
       
-rw-rw-r-- 1 fireway fireway 0 11月  3 07:55 test.c 
       
$ 
       ls -lu test test.c     
       <----------------检查最后访问时间 
       
-rwxrwxr-x 1 fireway fireway 0  8月 14 18:14 test 
       
-rw-rw-r-- 1 fireway fireway 0  9月  9 22:44 test.c 
       
$ 
       ls -lc test test.c     
       <-------------- 检查状态更改时间 
       
-rwxrwxr-x 1 fireway fireway 0 11月  3 07:55 test 
       
-rw-rw-r-- 1 fireway fireway 0 11月  3 07:55 test.c



    最后的访问时间没有修改,而修改时间和状态更改的时间则变更为程序运行的时间。



参考



UNIX环境高级编程(第三版)    4.20 函数futimens、utimensat和utimes