修改文件时间信息的函数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

相关文章

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

如何在运行时修改serialVersionUID

优质博文:IT-BLOG-CN 问题 我正在使用第三方库连接到外部系统,一切运行正常,但突然出现序列化错误 java.io.InvalidClassException: com.essbase.api.base.EssException; local class incompatible: stream classdesc serialVersionUID = 90314637791991

批处理以当前时间为文件名创建文件

批处理以当前时间为文件名创建文件 批处理创建空文件 有时候,需要创建以当前时间命名的文件,手动输入当然可以,但是有更省心的方法吗? 假设我是 windows 操作系统,打开命令行。 输入以下命令试试: echo %date:~0,4%_%date:~5,2%_%date:~8,2%_%time:~0,2%_%time:~3,2%_%time:~6,2% 输出类似: 2019_06