linux下遍历目录树方法总结,linux下遍历目录树方法总结(下)
2、使用ftw調(diào)用遍歷目錄
2.1ftw函數(shù)族
使用readdir函數(shù)等實現(xiàn)遞歸遍歷目錄樹的方法比較原始,glibc2.1收錄了ftw等函數(shù),可以方便實現(xiàn)目錄樹的遍歷。
#include?
intftw(constchar*dirpath,
int(*fn)?(constchar*fpath,conststructstat?*sb,inttypeflag),
intnopenfd);
#define?_XOPEN_SOURCE?500
#include?
intnftw(constchar*dirpath,
int(*fn)?(constchar*fpath,conststructstat?*sb,inttypeflag,structFTW?*ftwbuf),
intnopenfd,intflags);
具體的英文解釋可以參考文章《 ftw, nftw - file tree walk 》。
ftw()
函數(shù)說明:ftw() 會從參數(shù)dirpath指定的目錄開始,往下一層層地遞歸式遍歷子目錄。每一個文件或者目錄會調(diào)用參數(shù)*fn定義的函數(shù)來處理。ftw()會傳三個參數(shù)給fn(), 第一個參數(shù)*fpath指向當(dāng)時所在的目錄路徑,第二個參數(shù)是*sb, 為stat結(jié)構(gòu)指針,第三個參數(shù)為flag,有下面幾種可能值
FTW_F??????? 一般文件
FTW_D?????? 目錄
FTW_DNR??? 不可讀取的目錄,此目錄以下將不被遍歷
FTW_SL?????? 符號連接
FTW_NS?????? 無法取得stat結(jié)構(gòu)數(shù)據(jù),有可能是權(quán)限問題
最后一個參數(shù)depth代表ftw()在進(jìn)行遍歷目錄時同時打開的文件數(shù)。ftw()在遍歷時每一層目錄至少需要一個文件描述詞,如果遍歷時用完了depth所給予的限制數(shù)目,整個遍歷將因不斷地關(guān)文件和開文件操作而顯得緩慢。(實際做測試的時候未發(fā)現(xiàn)...)
如果要結(jié)束ftw()的遍歷,fn()只需返回一非零值即可,此值同時也會是ftw()的返回值。否則ftw()會試著走完所有的目錄,然后返回0
返 回? 值:遍歷中斷則返回fn()函數(shù)的返回值,全部遍歷則返回0,若有錯誤發(fā)生則返回-1
附加說明:由于ftw()會動態(tài)配置內(nèi)存使用,請使用正常方式(fn函數(shù)返回非零值)來中斷遍歷,不要在fn函數(shù)中使用longjmp()
nftw()
函數(shù)說明:nftw()與ftw()很像,都是從參數(shù)dirpath指定的目錄開始, 往下一層層地遞歸遍歷子目錄。 每一個文件或者目錄會調(diào)用參數(shù)*fn定義的函數(shù)來處理。nftw()會傳四個參數(shù)給fn(). 第一個參數(shù)*fpath指向當(dāng)時所在的目錄路徑,第二個參數(shù)是*sb, 為stat結(jié)構(gòu)指針(結(jié)構(gòu)定義請參考stat()),第三個參數(shù)為typeflag,有底下幾種可能值:
FTW_F???????????????????????? 一般文件
FTW_D???????????????????????? 目錄
FTW_DNR????????????????????? 不可讀取的目錄。此目錄以下將不被遍歷
FTW_SL???????????????????????? 符號連接
FTW_NS??????????????????????? 無法取得stat結(jié)構(gòu)數(shù)據(jù),在可能是權(quán)限問題
FTW_DP??????????????????????? 目錄,而且子目錄都已被遍歷過了
FTW_SLN?????????????????????? 符號連接,但連接不存在的文件
fn()的第四個參數(shù)是FTW結(jié)構(gòu),定義如下:
struct? FTW
{
int? base;
int? level; //level代表遍歷時的深度
}
nftw()第三個參數(shù)depth代表nftw()在進(jìn)行遍歷目錄時可同時打開的文件數(shù)。
ftw()在遍歷時每一層目錄至少需要一個文件描述詞,如果遍歷時用完了depth所給予的限制數(shù)目,整個遍歷將因不斷地關(guān)文件和開文件操作而顯得的緩慢
nftw()最后一個參數(shù)flags用來指定遍歷時的動作,可指定下列的操作或用OR組合
FTW_CHDIR???????????????? 在讀目錄之前先用chdir()移到此目錄
FTW_DEPTH??????????????? 執(zhí)行深度優(yōu)先搜索。在遍歷此目錄前先將所有子目錄遍歷完
FTW_MOUNT?????????????? 遍歷時不要跨越到其他文件系統(tǒng)
FTW_PHYS????????????????? 不要遍歷符號連接的目錄。預(yù)設(shè)會遍歷符號連接目錄
如果要結(jié)束nftw()的遍歷,fn()只需返回一非0值即可,此值同時也會是nftw()的返回值。否則nftw()會試著遍歷完所有目錄,然后返回0.
返 回 值 :遍歷中斷則返回fn()函數(shù)的返回值, 全部遍歷完則返回0,若有錯誤發(fā)生則返回-1
區(qū)別:ftw 對于每一個文件他都會調(diào)用stat函數(shù),這就造成程序會跟隨符號鏈接。這就可能導(dǎo)致在某些情況下重復(fù)某些目錄或者循環(huán)統(tǒng)計某些目錄文件(這是因為符號鏈接的原因,詳細(xì)參見UNIX環(huán)境高級編程)。
nftw將調(diào)用lstat函數(shù)所以不存在跟隨符號鏈接的問題。
有一個沒搞清楚的問題是我使用FTW_DEPTH?來遍歷整個目錄樹的時候,遍歷到proc目錄下存在異常返回,可能還需要指定FTW_PHYS使其不遍歷符號鏈接目錄,這個有空查一下。
2、遍歷的例子
自己寫的一個測試的小例子。遍歷指定目錄,輸出文件元數(shù)據(jù)和遍歷深度等信息。
#define?_XOPEN_SOURCE?500
#include
#include
#include
#include
#include
#define?FILEOPEN?1024
intgb_filecount;
intgetMetadata(constchar*dirpath,conststructstat?*sb,inttypeflag,structFTW?*ftwbuf);
intmain(intargc,char**?argv){
intret?=?0;
structstat?pathbuf;
if(argc?>?2){
printf("-nfwt_t:invalid?arguments \n?");
return-1;
}
if(stat(argv[1],&pathbuf)){
printf("-nfwt_t:invalid?dirpath:%s\n",argv[1]);
return-1;
}else{
if(0?==?S_ISDIR(pathbuf.st_mode)){
printf("-nfwt_t:\"%s\"?is?not?dirpath\n",argv[1]);
return-1;
}
}
gb_filecount=0;
ret?=?nftw(argv[1],getMetadata,FILEOPEN,FTW_PHYS);
if(ret<0){
printf("-nftw:[wrong:%d]ntfw?search?%d?files\n",ret,gb_filecount);
return-1;
}else{
printf("-nftw:[done:%d]trasvers?in?%s?search?%d?files\n",ret,argv[1],gb_filecount);
return0;
}
}
int
getMetadata(constchar*dirpath,conststructstat?*sb,inttypeflag,structFTW?*ftwbuf){
printf("num:%d?path:%s?",++gb_filecount,dirpath);
printf("st_dev:%d?",(*sb).st_dev);
printf("st_ino:%d?",(*sb).st_ino);
printf("st_mode:%d?S_ISDIR:%d?",(*sb).st_mode,S_ISDIR((*sb).st_mode));
printf("st_nlink:%d?",(*sb).st_nlink);
printf("st_uid:%d?",(*sb).st_uid);
printf("st_gid:%d?",(*sb).st_gid);
printf("st_rdev:%d?",(*sb).st_rdev);
printf("st_size:%d?",(*sb).st_size);
printf("st_blksize:%lu?",(*sb).st_blksize);
printf("st_blocks:%lu?",(*sb).st_blocks);
printf("st_atime:%ld?",(*sb).st_atime);
printf("st_mtime:%ld?",(*sb).st_mtime);
printf("st_ctime:%ld?",(*sb).st_ctime);
printf("typeflag:%d?",typeflag);
printf("FTW_base:%d?FTW_level:%d?/n",(*ftwbuf).base,(*ftwbuf).level);
return0;
}
總結(jié)
以上是生活随笔為你收集整理的linux下遍历目录树方法总结,linux下遍历目录树方法总结(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外媒:特斯拉在中国或赢得价格战 却会输掉
- 下一篇: 福特宣布将投资 35 亿美元与宁德时代一