首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

《APUE》:递归遍历索引层次结构,并按文件类型计数

2012-09-13 
《APUE》:递归遍历目录层次结构,并按文件类型计数《Unix环境高级编程》这本书附带了许多短小精美的小程序,我在

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

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


//《APUE》程序4-7://递归遍历目录层次结构,并按文件类型计数#include <unistd.h>#include <utime.h>#include <dirent.h>#include <sys/stat.h>#include <stdio.h>#include <limits.h>#include <stdlib.h>#include <string.h>typedef int Myfunc(const char*, const struct stat*, int);static Myfunc myfunc;static int myftw(char*, Myfunc*);static int dopath(Myfunc*);static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;int main(int argc, char **argv){int ret;if( argc != 2 ){fprintf(stderr, "Usage: ftw <starting-pathname>\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);return ret;}#define FTW_F 1#define FTW_D 2#define FTW_DNR 3#define FTW_NS 4static char *fullpath;static int myftw(char *pathname, Myfunc *func){//《APUE》书中,这个功能用了一个很复杂的函数path_alloc()来实现//这里我为了简单起见,直接为它分配了一段内存完事#ifdef PATH_MAXconst int PATH_LEN = PATH_MAX;#elseconst int PATH_LEN = 1024;#endiffullpath = malloc(PATH_LEN);strncpy(fullpath, pathname, PATH_LEN);fullpath[PATH_LEN-1] = '\0';int res = dopath(func);//《APUE》书中,好像没有释放这段内存free(fullpath);return res;}static int dopath(Myfunc* func){struct stat statbuf;struct dirent *dirp;DIR *dp;int ret;char *ptr;int temp;temp = lstat(fullpath, &statbuf);//文件状态错误if( temp < 0 )return func(fullpath, &statbuf, FTW_NS);temp = S_ISDIR(statbuf.st_mode);//不是文件夹if( 0 == temp )return func(fullpath, &statbuf, FTW_F);ret = func(fullpath, &statbuf, FTW_D);if( ret != 0 )return ret;ptr = fullpath + strlen(fullpath);*ptr++ = '/';*ptr = 0;dp = opendir(fullpath);//不能读取该文件夹if( NULL == dp )return func(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) < 0 ){fprintf(stderr, "can't close directory %s\n", fullpath);}return ret;}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++; printf("reg: %s\n", fullpath); break;case S_IFBLK: nblk++; printf("blk: %s\n", fullpath); break;case S_IFCHR: nchr++; printf("chr: %s\n", fullpath);break;case S_IFIFO: nfifo++; printf("fifo: %s\n", fullpath);break;case S_IFLNK: nslink++; printf("slink: %s\n", fullpath);break;case S_IFSOCK: nsock++; printf("socket: %s\n", fullpath);break;case S_IFDIR: fprintf(stderr, "For S_IFDIR for %s\n", pathname);exit(1);}//《APUE》书中没有输出遍历的结果,这个是我自己加上去的break;case FTW_D:ndir++; printf("DIR: %s\n", fullpath);break;case FTW_DNR:fprintf(stderr, "can't read directory %s\n", pathname);break;case FTW_NS:fprintf(stderr, "stat error for %s\n", pathname);break;default:fprintf(stderr, "unkown type %d for pathname %s\n", type, pathname);}return 0;}


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

qch@ubuntu:~/code$ gcc temp.c -o temp

qch@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 % 

热点排行