代码:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <dirent.h> #include <limits.h> /* function type that is 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){ fprintf(stderr,"usage: ftw <starting-pathname>\n"); exit(1); } ret = myftw(argv[1],myfunc); /* does it all */ ntot = nreg + ndir + nblk + nchr + nfile + nslink + nsock; if(ntot == 0) /* aoid divide by 0;print 0 for all counts */ ntot = 1; printf("regular files = %7ld, %5.2f %%\n",nreg,nreg*100.0/ntot); printf("directories = %7ld, %5.2f %%\n",ndir,ndir*100.0/ntot); printf("block special = %7ld, %5.2f %%\n",nblk,nblk*100.0/ntot); printf("char special = %7ld, %5.2f %%\n",nchr,nchr*100.0/ntot); printf("FIFOs = %7ld, %5.2f %%\n",nfifo,nfifo*100.0/ntot); printf("symbolic links = %7ld, %5.2f %%\n",nslink,nslink*100.0/ntot); printf("sockets = %7ld, %5.2f %%\n",nsock,nsock*100.0/ntot); exit(ret); } /* * Descend through the hierarchy,starting at "pathname". * The Caller's func() is called for every file. */ #define FTW_F 1 /* File oter than directory */ #define FTW_D 2 /* Directory */ #define FTW_DNR 3 /* Directory that can't be read */ #define FTW_NS 4 /* File that we can't stat */ static char *fullpath; /* contains full pathname for every file */ static int myftw(char *pathname,Myfunc *func) { int len; fullpath = path_alloc(&len); /* malloc's for PATH_MAX+1 bytes */ strncpy(fullpath,pathname,len); /* protect against */ fullpath[len-1] = 0; /* buffer overrun */ return(dopath(func)); } /* * Descend through the hierarchy,starting at "fullpath". * If "fullpath" is anything other than a directory,we lstat() it, * call func(),and return. For a directory,we call ourself * recursvely for each name in the directory. */ static int dopath(Myfunc *func) /* we return whatever func() returns */ { 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 dircetory. First call func() for the directory, * then process each filename in the directory. */ if((ret = func(fullpath,&statbuf,FTW_D)) != 0) return (ret); ptr = fullpath + strlen(fullpath); /* point to end of fullpath */ *ptr++ = '/'; *ptr = 0; if((dp = opendir(fullpath)) == NULL) /* can't read directory */ return(func(fullpath,&statbuf,FTW_DNR)); while((dirp = readdir(dp)) != NULL){ if(strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0) /* ignore dot and dot-dot */ continue; strcpy(ptr,dirp->d_name); /* append name after slash */ if((ret = dopath(func)) != 0) /* recursive */ break; /* time to leave */ } ptr[-1] = 0; /* erase everything from alash onwards */ if(closedir(dp) < 0){ fprintf(stderr,"Can't close directory %s",fullpath); exit(-1); } 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: fprintf(stderr,"for S_IFDIR for %s\n",pathname); /* directories should have type = FTW_D */ } case FTW_D: ndir++; 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,"unknown type %d for pathname %s",type,pathname); } return 0; } }
另一種列出目錄的demo,比較簡單,如下:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <dirent.h> /* * 功能描述: * 根據用戶輸入的目錄來逐級打印目錄名字 */ void printdir(char *dir,int depth) { DIR *dp; struct dirent *entry; struct stat statbuf; if((dp = opendir(dir)) == NULL){ fprintf(stderr,"Can't Open directory: %s\n",dir); return; } chdir(dir); while((entry = readdir(dp)) != NULL){ lstat(entry->d_name,&statbuf); if(S_ISDIR(statbuf.st_mode)){ /* Found a directory,but we should ignore . and .. */ if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0) continue; printf("%*s%s/\n",depth,"",entry->d_name); /* Recurse at a new indent level */ printdir(entry->d_name,depth+4); } else printf("%*s%s\n",depth,"",entry->d_name); } chdir(".."); /* 返回上級目錄并關閉,可以看出,如果目錄深度很大的話, */ closedir(dp); /* 有可能會報錯,原因是單個進程所能打開的最大文件數 */ } int main(int argc,char **argv) { char *topdir="."; if(argc != 2){ fprintf(stderr,"usage: ./a.out <pathname#>\n"); exit(0); } topdir=argv[1]; printf("Directory scan of %s:\n",topdir); printdir(topdir,0); printf("done.\n"); exit(0); }
其實這兩個例子的實質都是一樣的。