这篇文章的所有代码来自《UNIX环境高级编程》
统计某个目录的不同文件类型的数目及比例
#include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <limits.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> char * path_alloc(int *size); /* function type that's called for each filename */ 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){ printf("usage : ftw <starting-pathname> "); } /*does it all*/ ret=myftw(argv[1],myfunc); if( (ntot=nreg+ndir+nblk+nchr+nfifo+nslink+nsock)==0 ){ ntot=1; } printf("Regular files = %7ld,%5.2f%%\n",nreg,(nreg*100.0)/ntot); printf("Directories files = %7ld,%5.2f%%\n",ndir,(ndir*100.0)/ntot); printf("Block special files = %7ld,%5.2f%%\n",nblk,(nblk*100.0)/ntot); printf("Char special files = %7ld,%5.2f%%\n",nchr,(nchr*100.0)/ntot); printf("FIFO files = %7ld,%5.2f%%\n",nfifo,(nfifo*100.0)/ntot); printf("Symbolic link files = %7ld,%5.2f%%\n",nslink,(nslink*100.0)/ntot); printf("Sockets files = %7ld,%5.2f%%\n",nsock,(nsock*100.0)/ntot); exit(ret); } /* *Desend through the hierarchy,starting at "pathname" *The caller's fun() is called for every file */ #define FTW_F 1 /*file other than directory*/ #define FTW_D 2 /*director*/ #define FTW_DNR 3 /*director that can't be read*/ #define FTW_NS 4 /*file that we can't stat*/ /* *constains full pahtname for every file *malloc's for PATH_MAX+1 bytes *not release at last in code. */ static char *fullpath=path_alloc(NULL); static int myftw(char *pathname,Myfunc *func){ /*initialize fullpath*/ strcpy(fullpath,pathname); return( dopath(func) ); } /* *Desend through the hierarchy,starting at "fullpath" *If "fullpath" is anything other than a directory ,we lstat() it *call fun(),and return.For a directory ,we call ourself *recursively for each name in the directory */ static int dopath(Myfunc *func){ struct stat statbuf; struct dirent *dirp; DIR *dp; int ret; char *ptr; if( lstat(fullpath,&statbuf)<0 ){ /*stat error*/ return ( func(fullpath,&statbuf,FTW_NS) ); } if( S_ISDIR(statbuf.st_mode)==0 ){ /*not a directory*/ return ( func(fullpath,&statbuf,FTW_F) ); } /* *It's a directory.First call func() for the directory, *then process filename in directory. */ if( (ret=func(fullpath,&statbuf,FTW_D)) !=0 ){ return(ret); } /*point to the end of fullpath */ ptr=fullpath +strlen(fullpath); *ptr++='/'; *ptr=0; if( (dp=opendir(fullpath))==NULL ){ /*can't read directory*/ return( func(fullpath,&statbuf,FTW_DNR) ); } while( (dirp=readdir(dp))!=NULL ){ /*ignore dot and dot-dot*/ if( (strcmp(dirp->d_name,".")==0)|| (strcmp(dirp->d_name,"..")==0) ) { continue; } /*append name after slash*/ strcpy(ptr,dirp->d_name); if( (ret=dopath(func))!=0 ){ break; } } /*erase everything from slash onwards*/ ptr[-1]=0; if( closedir(dp)<0 ){ printf("Can't close directory %s.\n",fullpath); exit(0); } 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++; 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: /*directories should have type = FTW_D*/ printf("For S_IFDIR for %s",pathname); exit(0); break; } case FTW_D: ndir++; break; case FTW_DNR: printf("Can't read directory %s\n",pathname); return 0; break; case FTW_NS: printf("Stat error for %s\n",pathname); return 0; break; default: printf("Unknown type %d for pathname %s\n",type,pathname); } return 0; } #ifdef PATH_MAX static int pathmax=PATH_MAX; #else static int pathmax=0; #endif #define PATH_MAX_GUESS 256 /*allocate memory for pathname*/ char * path_alloc(int *size){ char *ptr; if(pathmax==0){ errno=0; if( (pathmax=pathconf("/",_PC_PATH_MAX)) <0){ if(errno==0){ pathmax=PATH_MAX_GUESS; } else{ perror("Error in pathconf ."); } } else{ pathmax++; } } if( (ptr=malloc(pathmax+1)) ==NULL){ perror("Error in malloc ."); } if(size!=NULL){ *size=pathmax+1; } return ptr; }