Linux環境下用C++刪除指定文件


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()函數執行文件的刪除操作。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM