linux ftw()函數使用方法 實例

表頭文件:#include <ftw.h>
定義函數:int ftw(const char *dir, int (*fn) (const *file, const struct stat *sb, int flag), int depth)
函數說明:ftw() 會從參數dir指定的 目錄開始,往下一層層地遞歸式遍歷子 目錄。ftw()會傳三個參數給fn(), 第一個參數*file指向當時所在的 目錄路徑,第二個參數是*sb, 爲stat結構指針,第三個參數爲旗標,有下面幾種可能值:
FTW_F 一般文件
FTW_D 目錄
FTW_DNR 不可讀取的 目錄,此 目錄以下將不被遍歷
FTW_SL 符號連接
FTW_NS 無法取得stat結構數據,有可能是 權限問題

最後一個參數depth代表ftw()在進行遍歷 目錄時同時打開的文件數。ftw()在遍歷時每一層 目錄至少需要一個文件描述詞,如果遍歷時用完了depth所給予的限制數目,整個遍歷將因不斷地關文件和開文件操作而顯得緩慢.
如果要結束ftw()的遍歷,fn()只需返回一非零值即可,此值同時也會是ftw()的返回值。否則ftw()會試着走完所有的 目錄,然後返回0.

返回值:遍歷中斷則返回fn()函數的返回值,全部遍歷則返回0,若有錯誤發生則返回-1

函數定義: int nftw(const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag, struct FTW *s), depth, int flags);
說明: nftw()與ftw()很像, 都是從參數dir指定的目錄開始, 往下一層層地遞歸式遍歷子目錄. 每進入一個目錄, 便會調用參數*fn定義的函數來處理. nftw()會傳四個參數給fn(), 第一個參數*file指向當時所在的目錄路徑, 第二個參數是*sb, 爲stat結構指針(結構定義請參考stat()), 第三個參數爲旗標, 有以下幾種可能:
FTW_F 一般文件
FTW_D 目錄
FTW_DNR 不可讀取的目錄. 此目錄以下將不被遍歷
FTW_SL 符號連接
FTW_NS 無法取得stat結構數據, 有可能是權限問題
FTW_DP 目錄, 而且其子目錄都已被遍歷過了.
FTW_SLN 符號連接, 但連接不存在文件
fn()的第四個參數是FTW結構, 定義如下:
struct FTW{
int base;
int level;
}
level代表遍歷當時的深度, nftw()第三個參數depth代表nftw()在進行遍歷目錄時可同時打開的文件數. ftw()在遍歷時每一層目錄至少需要一個文件描述詞, 如果遍歷時用完了depth所給予的限制數目, 整個遍歷將因不斷地關閉文件和打開文件操作而顯得緩慢. nftw()最後一個參數flags用來指定遍歷時的動作, 可以指定下列的操作或用OR組合:
FTW_CHDIR 在讀目錄之前用chdir()移到此目錄
FTW_DEPTH 執行深度優先搜索. 在遍歷此目錄前先將所有子目錄遍歷完
FTW_MOUNT 遍歷時不要跨越到其他文件系統
FTW_PHYS 不要遍歷符號連接的目錄. 預設會遍歷符號連接目錄
如果要結束ftw()的遍歷, fn()只需返回一非零值即可, 此值同時也會是ftw()的返回值, 否則ftw()會試着走完所有的目錄, 然後返回0. 遍歷中斷則返回fn()函數的返回值, 全部遍歷完則返回0. 如有錯誤發生則返回-1.
附加說明: 由於ftw()會動態配置內存使用, 請使用正常方式(fn函數返回非0值)來中斷遍歷, 不要在fn函數中使用longjmp().

照着定義寫了下程序。

 

今天寫了個ftw()函數的程序 如下:

int copytoU_device(const char *file , const struct stat *sb ,int flag)

{

    if(flag == FTW_F)

    {

        printf("%s,--file\n",file);

    }

    else if(flag == FTW_D)

    {

        printf("%s--dir\n",file);

    }

    return 0;         1

}

int main(int argc ,char *argv[])

{

    int result = 0;

    int flag_ftw = 0;

    DIR *sp;

    if((sp = opendir(PATH)) == 0) //打開copy文件夾,不存在返回0

    {    perror("fail to open dir");

        return 0;

    }

    flag_ftw = ftw(PATH,copytoU_device,500);

    printf("%d\n",flag_ftw);

    closedir(sp);

    if(result == 1)

    {

        perror("success");

    }

}

剛開始 一直無法打出一個文件夾下的所有內容,所以上網查了一些資料,才知道少了上面紅色字體  注 1  的那個 return 0;

註釋: 如果要結束ftw()的遍歷,fn()只需返回一非零值即可,此值同時也會是ftw()的返回值。否則ftw()會試着走完所有的 目錄,然後返回0.

得到的結果:/root/kay/copy--dir

/root/kay/copy/b,--file

/root/kay/copy/a,--file

/root/kay/copy/kk--dir

/root/kay/copy/kk/1~,--file

/root/kay/copy/kk/1,--file

ftw()函數的遍歷拷貝功能可以嵌套到子文件夾下面的子文件比如 我最近寫的一個程序的功能是把一個文件夾下的文件和子文件夾(裏面也有文件)拷貝到另外一個文件夾下,並刪除原文件和原文件夾。通過ftw()函數可以輕鬆的把文件找出來,但是,要copy子文件夾下的文件時,就會提示 段錯誤 ,爲什麼呢 ?因爲,有子文件夾“阻礙”,解決的辦法很簡單 ------à只要在目的文件夾中建立個與原子文件相同的文件夾就可以了,它就成自動按照你程序的要求,把子文件夾中的內容拷貝過去。

如下程序:

    if(flag == FTW_F)

    {

        printf("%s--file\n",file);

        fd = fopen(file,"r");

        fw = fopen(newpath,"w");

       while((ch = fgetc(fd)) != EOF ) //讀取文件內容          

        {

            fputc(ch,fw);               //複製到新文件中

        }

        fclose(fw);

        fclose(fd);

        printf("error = %d\n",unlink(file)); //刪除舊文件

     

    }

    if(flag == FTW_D)

    {

        printf("%s--dir\n",file);

       mkdir(newpath,0777);       //在新路徑下創建新文件夾名

        if(!flag_rein)

        {

            countfile++;

        }

       rmdir(file);         //刪除原文件夾   由於文件夾下有文件所以第一次無法刪除

       

    }

     printf("%d -- countfile\n",countfile);

     free(newpath);

     newpath = NULL;

     return 0;

}

 

隨後遇到的問題是,由於文件夾下有文件(文件夾)所以第一次無法刪除,因此要刪除文件夾,只好再次進入ftw()函數,進行遍歷並刪除,要進入幾次呢?就是看你的原文件夾中嵌套了文件夾的層數了(記住你是否要刪除原文件夾)。

   這是個人的學習心得,和自己程序中的一部分,有不足之處,請一起探討共同學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章