修改文件时间信息的函数futimens、utimensat和utimes

2024-04-06 21:38

本文主要是介绍修改文件时间信息的函数futimens、utimensat和utimes,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

#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

(1)如果times参数是一个空指针,则访问时间和修改时间两者都设置为当前时间。

以一个图片为例,在/home/zhihui/Pictures 路径下有一个文件:book.jpg

现将修改时间mtime,访问时间atime,i节点更改时间ctime 输出如下:

现修改这个文件的访问时间和修改时间

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>int main() {struct timespec time[2];int fd;fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);if(fd == -1){printf("open file failed.\n");}else{if(-1 == futimens(fd,NULL)){printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}}return 0;
}

由下图可见,当times参数空指针时,文件的访问时间,修改时间(包括i节点修改时间)都变为Nov  1  11:18 

 

(2)如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_NOW,相应的时间戳就设置为当前时间,忽略相应的tv_sec字段。

代码如下,我们仅将time[0]的tv_nsec设置为UTIME_NOW 其他成员采用系统默认值。

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>int main() {struct timespec time[2];time[0].tv_nsec = UTIME_NOW;int fd;fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);if(fd == -1){printf("open file failed.\n");}else{if(-1 == futimens(fd,time)){printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}}return 0;
}

运行后结果如下:

 $ ls -al | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Feb 18  1970 book.jpg$ ls -al --time=atime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 11:36 book.jpg$ ls -al --time=ctime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 11:36 book.jpg

值得注意的一点是,文件的修改时间(mtime)变为了Feb 18 1970

只有atime和ctime变为了当前时间。

我们对上面的代码稍作修改

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>int main() {struct timespec time[2];time[0].tv_nsec = UTIME_NOW;time[1].tv_nsec = UTIME_NOW;int fd;fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);if(fd == -1){printf("open file failed.\n");}else{if(-1 == futimens(fd,time)){printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}}return 0;
}


 增加了

time[1].tv_nsec = UTIME_NOW;

因为第一个time的第一个元素包含访问时间,第二个元素包含修改时间。将两个时间都设置为UTIME_NOW

运行结果如下

$ ls -al | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 11:41 book.jpg$ ls -al --time=atime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 11:41 book.jpg$ ls -al --time=ctime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 11:41 book.jpg

可以看到,文件的mtime 也变成了当前时间。

再做一点修改,将time[0].tv_nsec = UTIME_NOW;这一行注释

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>int main() {struct timespec time[2];
//    time[0].tv_nsec = UTIME_NOW;time[1].tv_nsec = UTIME_NOW;int fd;fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);if(fd == -1){printf("open file failed.\n");}else{if(-1 == futimens(fd,time)){printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}}return 0;
}

 

 

运行结果如下

$ ls -al | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 11:46 book.jpg$ ls -al --time=atime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Dec  6  4461538 book.jpg$ ls -al --time=ctime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 11:46 book.jpg

值得注意的是,atime 变成了Dec  6  4461538,由于访问时间未定义,因此呈现出来的时间格式也不正常。

现在再回过头来看这句话:如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_NOW,相应的时间戳就设置为当前时间,忽略相应的tv_sec字段。

也就是说,只将第一个数组元素的tv_nsec置为UTIME_NOW,则对应的访问时间就变成当前时间,只将第二个数组元素的tv_nsec置为UTIME_NOW,则对应的修改时间就变成当前时间。但是无论是那个元素的tv_nsec置为UTIME_NOW,文件的ctime即i节点修改时间都会变为当前时间。

(3)如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_OMIT,相应的时间戳保持不变,忽略相应的tv_sec字段。

我们读取文件a的访问时间和修改时间,并将这个时间存储到time结构体中.然后将文件b的时间状态设为当前时间,再用time结构体中保存的时间去设置文件b的访问时间和修改时间并将time结构体数组其中一个元素的tv_nsec设置为UTIME_OMIT。比如,在目录/home/zhihui/Pictures 下有文件 container.odg ,我们先从命令行查询这个文件的时间信息,得到如下信息:

 $ ls -al | grep container.odg 
-rw-rw-r--  1 zhihui zhihui 269171 Sep 12 09:24 container.odg$ ls -al --time=ctime | grep container.odg 
-rw-rw-r--  1 zhihui zhihui 269171 Sep 12 09:24 container.odg$ ls -al --time=atime -h  | grep container.odg 
-rw-rw-r--  1 zhihui zhihui 263K Sep 12 09:24 container.odg

编写如下代码 

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main() {struct timespec time[2];struct stat buf[10];int fd;fd = open("/home/zhihui/Pictures/container.odg",O_RDONLY);fstat(fd,buf);close(fd);time[0] = buf[0].st_atim;time[1] = buf[0].st_mtim;time[1].tv_nsec = UTIME_OMIT;fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);if(fd == -1){printf("open file failed.\n");}else{if(-1 == futimens(fd,NULL)){            //设为当前时间printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}if(-1 == futimens(fd,time)){printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}}close(fd);return 0;
}

执行结果如下:

$ ls -al | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 18:19 book.jpg$ ls -al --time=ctime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 18:19 book.jpg$ ls -al --time=atime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Sep 12 09:24 book.jpg

我们将time0设置为了和container.odg的访问时间时间 Sep 12 09:24 ,time[0]改变的是文件的访问时间,所以我们看到atime 变为了Sep 12 09:24。另一方面time[1]的tv_nsec被设置为UTIME_OMIT,因此time[1]的tv_sec总的数据被忽略,因而文件的修改时间依然是当前时间。

(4)如果 times 参数指向两个 timespec 结构的数组,且 tv_nsec 字段的值为既不是UTIME_NOW 也不是 UTIME_OMIT,在这种情

况下,相应的时间戳设置为相应的 tv_sec 和tv_nsec字段的值。

我们使用和上面相同的方法。查询文件a的访问时间和修改时间,并将这个时间存储到time结构体中.然后将文件b的时间状态设为当前时间,再用time结构体中保存的时间去设置文件b的访问时间和修改时间

编写如下代码: 

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main() {struct timespec time[2];struct stat buf[10];int fd;fd = open("/home/zhihui/Pictures/container.odg",O_RDONLY);fstat(fd,buf);close(fd);time[0] = buf[0].st_atim;time[1] = buf[0].st_mtim;fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);if(fd == -1){printf("open file failed.\n");}else{if(-1 == futimens(fd,NULL)){            //设为当前时间printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}if(-1 == futimens(fd,time)){printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}}close(fd);return 0;
}

 

$ ls -al | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Sep 12 09:24 book.jpg$ ls -al --time=ctime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 18:36 book.jpg$ ls -al --time=atime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Sep 12 09:24 book.jpg

可以看到文件的读取时间和修改时间都已经改变。

 

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

struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
编写如下代码,将文件读取时间设置为1970年1月3号,文件修改时间设置为1970年1月4号:

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>int main() {struct timeval time[2];time[0].tv_sec =  2 * 24*60*60 + 26 * 60;time[0].tv_usec = 0;time[1].tv_sec =  3 * 24*60*60 + 44 * 60;time[1].tv_usec = 0;if(-1 == utimes("/home/zhihui/Pictures/book.jpg",time)){printf("modify time failed.\n");}else{printf("modify time cucceed.\n");}return 0;
}

 运行结果如下:

$ ls -al | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Jan  4  1970 book.jpg$ ls -al --time=ctime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Nov  1 19:40 book.jpg$ ls -al --time=atime | grep book
-rw-rw-r--  1 zhihui zhihui  26786 Jan  3  1970 book.jpg

 

这篇关于修改文件时间信息的函数futimens、utimensat和utimes的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/880896

相关文章

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

MySQL按时间维度对亿级数据表进行平滑分表

《MySQL按时间维度对亿级数据表进行平滑分表》本文将以一个真实的4亿数据表分表案例为基础,详细介绍如何在不影响线上业务的情况下,完成按时间维度分表的完整过程,感兴趣的小伙伴可以了解一下... 目录引言一、为什么我们需要分表1.1 单表数据量过大的问题1.2 分表方案选型二、分表前的准备工作2.1 数据评估

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数

python中update()函数的用法和一些例子

《python中update()函数的用法和一些例子》update()方法是字典对象的方法,用于将一个字典中的键值对更新到另一个字典中,:本文主要介绍python中update()函数的用法和一些... 目录前言用法注意事项示例示例 1: 使用另一个字典来更新示例 2: 使用可迭代对象来更新示例 3: 使用