表頭文件:#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()函數,進行遍歷並刪除,要進入幾次呢?就是看你的原文件夾中嵌套了文件夾的層數了(記住你是否要刪除原文件夾)。
這是個人的學習心得,和自己程序中的一部分,有不足之處,請一起探討共同學習。