本节主要讲述了对unix系统对读目录的讲述。首先了解一下了解一下下面的函数
#include <dirent.h>
DIR* opendir(const char* pathname);
成功返回指针,错误返回null;
struct dirent *readdir(DIR *dp);//成功返回其指针,若在目录结尾或出错则返回null;
void rewinddir(DIR* dp);
int closedir(DIR* dp);//成功返回0,出错返回-1;
long telldir(DIR* dp);//返回与dp关联的目录中的当前的位置
void seekdir(DIR * dp,long loc);
struct dirent * readdir (DIR *dirstream) [Function]
This function reads the next entry from the directory. It normally returns a pointer to
a structure containing information about the file. This structure is statically allocated
and can be rewritten by a subsequent call.
Portability Note: On some systems readdir may not return entries for ‘.’ and ‘..’,
even though these are always valid file names in any directory. See Section 11.2.2
[File Name Resolution], page 224.
If there are no more entries in the directory or an error is detected, readdir returns
a null pointer. The following errno error conditions are defined for this function:
EBADF The dirstream argument is not valid.
readdir is not thread safe. Multiple threads using readdir on the same dirstream
may overwrite the return value. Use readdir_r when this is critical.
int closedir (DIR *dirstream) [Function]
This function closes the directory stream dirstream. It returns 0 on success and -1
on failure.
The following errno error conditions are defined for this function:
EBADF The dirstream argument is not valid.
其他的就不写了,本章主要是通过运用以上函数来实现遍历目录层次结构,并按文件类型进行技术。
直接上代码:
#include "apue.h"
#include <dirent.h>
#include<limits.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)
err_quit("usage:ftw<starting-pathname>");
ret=myftw(argv[1],myfunc);
ntot=nreg+ndir+nblk+nchr+nfifo+nslink+nsock;
if(ntot==0)
ntot=1;
printf("regular files= %7ld,%5.2f %%\n",nreg,nreg*100.0/ntot);
printf("regular files= %7ld,%5.2f %%\n",ndir,ndir*100.0/ntot);
printf("regular files= %7ld,%5.2f %%\n",nblk,nblk*100.0/ntot);
printf("regular files= %7ld,%5.2f %%\n",nchr,nchr*100.0/ntot);
printf("regular files= %7ld,%5.2f %%\n",nfifo,nfifo*100.0/ntot);
printf("regular files= %7ld,%5.2f %%\n",nslink,nslink*100.0/ntot);
printf("regular files= %7ld,%5.2f %%\n",nsock,nsock*100.0/ntot);
}
char*path_alloc(int* size)
{
char *p = NULL;
if(!size) return NULL;
p = malloc(256);
if(p)
*size = 256;
else
*size = 0;
return p;
}
#define FTW_F 1
#define FTW_D 2
#define FTW_DNR 3
#define FTW_NS 4
static char *fullpath;
static int myftw(char* pathname,Myfunc* func)
{
int len;
fullpath=path_alloc(&len);
strncpy(fullpath,pathname,len);
fullpath[len-1]=0;
return (dopath(func));
}
static int dopath(Myfunc* func)
{
struct stat statbuf;
struct dirent *dirp;
DIR* dp;
int ret;
char *ptr;
if(lstat(fullpath,&statbuf)<0)
return (func(fullpath,&statbuf,FTW_NS));
if(S_ISDIR(statbuf.st_mode)==0)
return (func(fullpath ,&statbuf, FTW_F));
if((ret=func(fullpath,&statbuf,FTW_D))!=0)
return (ret);
ptr=fullpath+strlen(fullpath);
*ptr++='/';
*ptr=0;
if((dp=opendir(fullpath))==NULL)
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);
if((ret=dopath(func))!=0)
break;
}
ptr[-1]=0;
if(closedir(dp)<0)
err_ret("can't clost dir %s",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++;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:
err_dump("for S_IFDIR for %s",pathname);
}
break;
case FTW_D:
ndir++;
break;
case FTW_DNR:
err_ret("can't read directory %s",pathname);
break;
case FTW_NS:
err_ret("stat error for %s",pathname);
break;
default:
err_dump("unkown type %d for pathname %s",type,pathname);
}
return(0);
}
这个经过修正可以正常运行了
运行结果