”Talk is cheap, show me the code!“
#include <cstdio>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>
#include <vector>
#include <dirent.h>
#include <time.h>
using namespace std;
const long day = 86400;
//获取文件的给更新时间
long get_file_modify_time(string filepath)
{
struct stat filehand;
FILE *fp;
fp = fopen(filepath.c_str(), "r");
int fileid = fileno(fp);
fstat(fileid, &filehand);
fclose(fp);
return filehand.st_mtime;
}
//获取文件夹中的所有文件
void get_files(const string dirname, vector<string> &filelist)
{
if(dirname.empty())
return;
struct stat s;
stat(dirname.c_str(), &s);
if(!S_ISDIR(s.st_mode))
return;
DIR *dirhand = opendir(dirname.c_str());
if(NULL == dirhand){
exit(EXIT_FAILURE);
}
dirent *fp = nullptr;
while((fp = readdir(dirhand)) != nullptr){
if(fp->d_name[0] != '.'){//十分重要的一行(?)
string filename = dirname + "/" + string(fp->d_name);
struct stat filemod;
stat(filename.c_str(), &filemod);
if(S_ISDIR(filemod.st_mode)){
get_files(filename, filelist);
}
else if(S_ISREG(filemod.st_mode)){
filelist.push_back(filename);
}
}
}
closedir(dirhand);
return;
}
bool delete_file(string filepath)
{
return remove(filepath.c_str());
}
bool date_from_now(long now, long modify)
{
int dis = int((1.0 * (now - modify) / day + 0.5));
return dis >= 9;//删除最近更新时间距今超过14天的文件
}
int main()
{
time_t now;
time(&now);//获取当前系统时间
string dir = "/file/cpp";//需要处理的文件夹
vector<string> filelist;
get_files(dir, filelist);//获取文件夹中的所有文件
for(auto i : filelist){
if(date_from_now(now, get_file_modify_time(i))){
cout << i << endl;
if(!delete_file(i)){
cout << "The file named : " << i << " has been deleted." << endl;
}
else{
cout << "Delete Failed!" << endl;
}
}
}
return 0;
}
如果没有详细学习过linux下编程,可能看不太懂这些代码,接下来详细分析:
自由互联热门推荐:PDF电子发票识别软件,一键识别电子发票并导入到Excel中!10大顶级数据挖掘软件!人工智能的十大作用!获取文件最后更新时间
对应代码
//获取文件的给更新时间
long get_file_modify_time(string filepath)
{
struct stat filehand;
FILE *fp;
fp = fopen(filepath.c_str(), "r");
int fileid = fileno(fp);
fstat(fileid, &filehand);
fclose(fp);
return filehand.st_mtime;
}
代码中用到了stat数据结构和文件操作,学过c的同学应该对文件操作都比较熟悉。
struct stat是一种保存文件信息的数据结构,使用这个结构体和一些相应的函数,需要包含
<sys/types.h>和<sys/stat.h>
对于一个文件我们可以用fstat函数来获取这个文件所对应的数据结构,fstat(int fid, struct stat *struct_stat)
其中fid为文件的描述符,可以理解为文件的一个唯一编号,获取这个编号我们就要用到文件操作函数。
首先用fopen()
打开文件并获取文件指针,之后用fileno()
获取文件的描述符。
对于struct stat中的属性包括:
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};
我们需要获取的是文件的最近更新时间,也就是st_mtime
(注意:这个属性所表示的时间是距离1970年1月1日0点0分0秒[国际标准时间]的秒数)。
获取所有的文件
对应代码
//获取文件夹中的所有文件
void get_files(const string dirname, vector<string> &filelist)
{
if(dirname.empty())
return;
struct stat s;
stat(dirname.c_str(), &s);
if(!S_ISDIR(s.st_mode))
return;
DIR *dirhand = opendir(dirname.c_str());
if(NULL == dirhand){
exit(EXIT_FAILURE);
}
dirent *fp = nullptr;
while((fp = readdir(dirhand)) != nullptr){
if(fp->d_name[0] != '.'){//十分重要的一行
string filename = dirname + "/" + string(fp->d_name);
struct stat filemod;
stat(filename.c_str(), &filemod);
if(S_ISDIR(filemod.st_mode)){
get_files(filename, filelist);
}
else if(S_ISREG(filemod.st_mode)){
filelist.push_back(filename);
}
}
}
closedir(dirhand);
return;
}
在这部分中我们要用到关于文件夹处理的一些函数和结构体,需要引入<dirent.h>头文件
在这部分中,首先我们要为函数传入两个参数,需要处理的文件所在的文件夹,和一个文件列表(用来保存所有文件的信息,这里用vector实现)
首先我们先将文件夹保存为struct stat变量,然后借助S_ISDIR()
函数来判断这是否是一个文件夹,如果不是则退出,如果是,我们要使用DIR结构体来保存文件夹的信息。
DIR可以定义一个文件夹结构体变量,其值由opendir(char *file_path)函数获得。
之后用dirent变量可以遍历文件夹中的所有文件,包括文件夹在内。dirent变量的值由readdir(DIR *p)函数获得。
dirent结构体中保存的属性有:
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
这里我们需要用到d_name字符串来获取文件名并组成文件路径,需要注意的是:在一个文件夹中最开始的两个目录是”.“文件和”..”文件,这个用vim打印文件树的时候可以看到,这两个分别代表当前目录和父目录,所以我们要在遍历时排除这两个文件,否则会产生无限递归,程序崩溃!!!
除了S_ISDIR()函数我们还会用到S_ISREG()函数,是为了判断文件是否为普通文件。
获取系统当前时间
time_t now;
time(&now);//获取当前系统时间
这里用到time()函数,需要包含<time.h>库
删除文件
bool delete_file(string filepath)
{
return remove(filepath.c_str());
}
c++可以使用remove()函数执行文件的删除操作。