readdir函數(shù)的使用方式
頭文件:
#include <sys/types.h>
#include <dirent.h>
定義函數(shù):
struct dirent * readdir(DIR * dir);
函數(shù)說(shuō)明:
返回值:成功則返回下個(gè)目錄進(jìn)入點(diǎn)恕出。有錯(cuò)誤發(fā)生或讀取到目錄文件尾則返回NULL.
結(jié)構(gòu)體dirent 定義如下(在linux下搜索dirent.h即可找到):
struct dirent
{
#ifndef __USE_FILE_OFFSET64
__ino_t d_ino;
__off_t d_off;
#else
__ino64_t d_ino;
__off64_t d_off;
#endif
unsigned short int d_reclen;
unsigned char d_type;
char d_name[256]; /* We must not include limits.h! */
};
調(diào)用opendir和readdir函數(shù)對(duì)指定目錄進(jìn)行遍歷操作非区,然后打印輸出指定目錄中各種類型的文件數(shù)目搪桂。
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <limits.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
typedef int Myfunc(const char *, const struct stat *, int); //定義一個(gè)函數(shù)
static Myfunc myfunc;
static int myftw(char *, Myfunc *);
static int dopath(Myfunc *);
static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;
//各種類型的文件數(shù)目對(duì)應(yīng)的變量
char *path_alloc(int* size);
int main(int argc, char *argv[])
{
int ret;
if (argc != 2)
{
printf("請(qǐng)輸入正確的參數(shù)!\n"); //參數(shù)錯(cuò)誤
return 1;
}
ret = myftw(argv[1], myfunc); /* does it all */
ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
//計(jì)算文件總量
if (ntot == 0) //如果目錄中沒(méi)有文件則將ntot設(shè)置為1以避免除數(shù)為0
{
ntot = 1;
}
//以下一次打印各種類型文件的數(shù)據(jù)
printf("普通文件 = %7ld, %5.2f %%\n", nreg, nreg*100.0/ntot);
printf("目錄文件 = %7ld, %5.2f %%\n", ndir,ndir*100.0/ntot);
printf("塊設(shè)備文件 = %7ld, %5.2f %%\n", nblk,nblk*100.0/ntot);
printf("字設(shè)備文件 = %7ld, %5.2f %%\n", nchr, nchr*100.0/ntot);
printf("FIFOs = %7ld, %5.2f %%\n", nfifo,nfifo*100.0/ntot);
printf("符號(hào)鏈接文件 = %7ld, %5.2f %%\n", nslink, nslink*100.0/ntot);
printf("套接字文件 = %7ld, %5.2f %%\n", nsock,nsock*100.0/ntot);
return ret;
}
//路徑緩沖區(qū)分配函數(shù)
char *path_alloc(int* size)
{
char *p = NULL;
if(!size)
{
return NULL;
}
p = malloc(256);
if(p)
{
*size = 256;
}
else
{
*size = 0;
}
return p;
}
#define FTW_F 1 //
#define FTW_D 2 //目錄
#define FTW_DNR 3 //不能讀的目錄
#define FTW_NS 4 //不能獲得狀態(tài)的文件
static char *fullpath; //存放每個(gè)文件完整路徑
static int myftw(char *pathname, Myfunc *func)
{
int len;
fullpath = path_alloc(&len); //給路徑緩沖區(qū)分配一個(gè)長(zhǎng)度
strncpy(fullpath, pathname, len); //復(fù)制文件名稱
fullpath[len-1] = 0; //給緩沖區(qū)的最后一位賦'\0'
return(dopath(func));
}
//獲得文件的狀態(tài)的函數(shù)
static int dopath(Myfunc* func)
{
struct stat statbuf;
struct dirent *dirp;
DIR *dp;
int ret; //返回標(biāo)記值诈悍,用于
char *ptr; //用于給fullpath加字符串,用來(lái)做子目錄探索
if (lstat(fullpath, &statbuf) < 0) //獲得文件狀態(tài)失敗就執(zhí)行,其中l(wèi)stat函數(shù)成功執(zhí)行時(shí)外盯,返回0惭墓。失敗返回-1
{
return(func(fullpath, &statbuf, FTW_NS));//工作正常時(shí)返回值為0
}
if (S_ISDIR(statbuf.st_mode) == 0) //如果不是目錄,則。膘融。芙粱。
{ //其中S_ISDIR為宏函數(shù),用于判斷是否目錄托启,如果是目錄宅倒,返回值為1
return(func(fullpath, &statbuf, FTW_F));//工作正常時(shí)返回值為0
}
if ((ret = func(fullpath, &statbuf, FTW_D)) != 0)//經(jīng)過(guò)以上if語(yǔ)句,運(yùn)行到這一步的為目錄文件,調(diào)用myfunc函數(shù)屯耸,目錄記錄數(shù)+1,然后記錄成功的話拐迁,ret的值為0,if中的語(yǔ)句就不會(huì)執(zhí)行
{
return(ret);//myfunc工作正常時(shí)返回值ret為0
}
ptr = fullpath + strlen(fullpath); //指向路徑緩沖區(qū)字符串的結(jié)尾,此時(shí)*ptr='/0'
*ptr++ = '/'; //相當(dāng)于*ptr='/';ptr++;
*ptr = 0;//當(dāng)前位置'\0'疗绣,用于字符串結(jié)尾定位线召,防止輸出亂碼
//---------------------------------------------------------------------------------------------------------------
//獲得子目錄文件的信息
if ((dp = opendir(fullpath)) == NULL) //調(diào)用opendir,其返回值為一個(gè)DIR類型指針多矮,如果值為NULL則讀取錯(cuò)誤或位于目錄尾
{
return(func(fullpath, &statbuf, FTW_DNR));//調(diào)用myfunc函數(shù)缓淹,不可讀的目錄+1
}
while ((dirp = readdir(dp)) != NULL) /*關(guān)鍵點(diǎn)!塔逃!readdir函數(shù)返回指向dirent結(jié)構(gòu)體類型的指針,返回值:成功則返回下個(gè)目錄進(jìn)入點(diǎn). 有錯(cuò)誤發(fā)生或讀取到目錄文件尾則返回NULL. */
{
if (strcmp(dirp->d_name, ".") == 0 ||strcmp(dirp->d_name, "..") == 0)//strcmp函數(shù)讯壶,如果兩個(gè)字符串相同則返回0
continue; /* 忽略.. 和. 文件 */
strcpy(ptr, dirp->d_name); /*把子文件名加入到*fullpath字符串后面,生成新的詳細(xì)路徑*/
if ((ret = dopath(func)) != 0) /* 嵌套獲取當(dāng)前的路徑的信息湾盗,如果有多個(gè)子目錄或者多個(gè)子文件伏蚊,都進(jìn)行統(tǒng)計(jì) */
break;//if語(yǔ)句是為了讓程序運(yùn)行出錯(cuò)就跳出當(dāng)前循環(huán)
}
//---------------------------------------------------------------------------------------------------------------
ptr--;
ptr = 0; /* 通過(guò)給斜線處賦值為'\0',相當(dāng)于刪除斜線后面添加的內(nèi)容,此處書(shū)上是ptr[-1]=0 */
if (closedir(dp) < 0)
{
printf("can't close directory %s\n", fullpath);
}
return(ret);//可能出錯(cuò)的位置
}
//統(tǒng)計(jì)函數(shù)
static int myfunc(const char *pathname, const struct stat *statptr, int type)
{
switch (type) {
case FTW_F:
switch (statptr->st_mode & S_IFMT) {
case S_IFREG: nreg++; break;
case S_IFBLK: nblk++; break;
case S_IFCHR: nchr++; break;
case S_IFIFO: nfifo++; break;
case S_IFLNK: nslink++; break;
case S_IFSOCK: nsock++; break;
case S_IFDIR:
printf("for S_IFDIR for %s\n", pathname);
}
break;
case FTW_D:
ndir++;
break;
case FTW_DNR:
printf("can't read directory %s\n", pathname);
break;
case FTW_NS:
printf("stat error for %s\n", pathname);
break;
default:
printf("unknown type %d for pathname %s\n", type, pathname);
}
return(0);
}