代码:
#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);
}
其實這兩個例子的實質都是一樣的。