linux下层次遍历目录,《APUE》:递归遍历目录层次结构,并按文件类型计数

《Unix环境高级编程》这本书附带了许多短小精美的小程序,我在阅读此书的时候,将书上的代码按照自己的理解重写了一遍(大部分是抄书上的),加深一下自己的理解(纯看书太困了,呵呵)。此例子在Ubuntu 10.04上测试通过。

相关链接

//《APUE》程序4-7:

//递归遍历目录层次结构,并按文件类型计数

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

typedefintMyfunc(constchar*,conststructstat*,int);

staticMyfunc myfunc;

staticintmyftw(char*, Myfunc*);

staticintdopath(Myfunc*);

staticlongnreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;

intmain(intargc,char**argv)

{

intret;

if( argc != 2 )

{

fprintf(stderr,"Usage: ftw \n");

exit(1);

}

ret = myftw(argv[1], myfunc);

ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;

//

if( 0 == ntot )

ntot = 1;

//输入各种文件的数量及所占的比例

printf("reglar files = %7ld, %5.2lf %% \n",

nreg, nreg*100.0/ntot);

printf("directories = %7ld, %5.2lf %% \n",

ndir, ndir*100.0/ntot);

printf("block special = %7ld, %5.2lf %% \n",

nblk, nblk*100.0/ntot);

printf("char special = %7ld, %5.2lf %% \n",

nchr, nchr*100.0/ntot);

printf("FIFOs = %7ld, %5.2lf %% \n",

nfifo, nfifo*100.0/ntot);

printf("symbolic links = %7ld, %5.2lf %% \n",

nslink, nslink*100.0/ntot);

printf("sockets = %7ld, %5.2lf %% \n",

nsock, nsock*100.0/ntot);

returnret;

}

#define FTW_F 1

#define FTW_D 2

#define FTW_DNR 3

#define FTW_NS 4

staticchar*fullpath;

staticintmyftw(char*pathname, Myfunc *func)

{

//《APUE》书中,这个功能用了一个很复杂的函数path_alloc()来实现

//这里我为了简单起见,直接为它分配了一段内存完事

#ifdef PATH_MAX

constintPATH_LEN = PATH_MAX;

#else

constintPATH_LEN = 1024;

#endif

fullpath = malloc(PATH_LEN);

strncpy(fullpath, pathname, PATH_LEN);

fullpath[PATH_LEN-1] ='\0';

intres = dopath(func);

//《APUE》书中,好像没有释放这段内存

free(fullpath);

returnres;

}

staticintdopath(Myfunc* func)

{

structstat statbuf;

structdirent *dirp;

DIR *dp;

intret;

char*ptr;

inttemp;

temp = lstat(fullpath, &statbuf);

//文件状态错误

if( temp 

returnfunc(fullpath, &statbuf, FTW_NS);

temp = S_ISDIR(statbuf.st_mode);

//不是文件夹

if( 0 == temp )

returnfunc(fullpath, &statbuf, FTW_F);

ret = func(fullpath, &statbuf, FTW_D);

if( ret != 0 )

returnret;

ptr = fullpath + strlen(fullpath);

*ptr++ ='/';

*ptr = 0;

dp = opendir(fullpath);

//不能读取该文件夹

if( NULL == dp )

returnfunc(fullpath, &statbuf, FTW_DNR);

while( (dirp = readdir(dp)) != NULL )

{

//忽略.和..这两个文件夹

if( strcmp(dirp->d_name,".") == 0 ||

strcmp(dirp->d_name,"..") == 0 )

continue;

strcpy(ptr, dirp->d_name);

//递归遍历各个子文件夹

ret = dopath(func);

if( ret != 0 )

break;

}

ptr[-1] = 0;

if( closedir(dp) 

{

fprintf(stderr,"can't close directory %s\n", fullpath);

}

returnret;

}

staticintmyfunc(constchar*pathname,conststructstat *statptr,inttype)

{

switch(type)

{

caseFTW_F:

switch( statptr->st_mode & S_IFMT )

{

caseS_IFREG:

nreg++;

printf("reg: %s\n", fullpath);

break;

caseS_IFBLK:

nblk++;

printf("blk: %s\n", fullpath);

break;

caseS_IFCHR:

nchr++;

printf("chr: %s\n", fullpath);

break;

caseS_IFIFO:

nfifo++;

printf("fifo: %s\n", fullpath);

break;

caseS_IFLNK:

nslink++;

printf("slink: %s\n", fullpath);

break;

caseS_IFSOCK:

nsock++;

printf("socket: %s\n", fullpath);

break;

caseS_IFDIR:

fprintf(stderr,"For S_IFDIR for %s\n", pathname);

exit(1);

}

//《APUE》书中没有输出遍历的结果,这个是我自己加上去的

break;

caseFTW_D:

ndir++;

printf("DIR: %s\n", fullpath);

break;

caseFTW_DNR:

fprintf(stderr,"can't read directory %s\n", pathname);

break;

caseFTW_NS:

fprintf(stderr,"stat error for %s\n", pathname);

break;

default:

fprintf(stderr,"unkown type %d for pathname %s\n",

type, pathname);

}

return0;

}

运行示例(加下划线的为输入):

www.linuxidc.com @ubuntu:~/code$ gcc temp.c -o temp

www.linuxidc.com @ubuntu:~/code$ ./temp /etc

DIR: /etc

DIR: /etc/sudoers.d

reg: /etc/sudoers.d/README

...............

reglar files =    1593, 59.89 %

directories =     306, 11.50 %

block special =       0,  0.00 %

char special =       0,  0.00 %

FIFOs =       0,  0.00 %

symbolic links =     761, 28.61 %

sockets =       0,  0.00 %0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值