Linux环境下用C++删除指定文件
”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下编程,可能看不太懂这些代码,接下来详细分析:
获取文件最后更新时间
对应代码
//获取文件的给更新时间 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()函数执行文件的删除操作。
来源:https://www.cnblogs.com/LeafLove/p/12512844.html