2020-10-19

本文记录《UNIX高级环境编程》一书中,递归遍历目录树的程序:1.程序4-22递归降序遍历目录层次结构,并按照文件类型进行计数。主要涉及到三个函数myftw()、dopath()和myfunc()。myftw ()函数以所带参数pathname为要遍历的起始目录,计算出该目录下各种不同类型的文件的个数和所占百分比,并显示出来。它调用了另外两个函数,一个是dopath()函数,这是一个递归函数,对指定的起始目录下的每个目录项,按深度优先进行遍历;而对所访问的节点,则调用myfunc()进行处理。main函数输出统计结果。三个函数的参数含义如下:
(1) static int myftw(char *pathname, Myfunc *func);
pathname给出指要遍历开始的目录。
func是Myfunc类型的函数指针,定义访问的实际操作。
(2) static int dopath(Myfunc *func);
pathname给出指要遍历开始的目录。
(3) static int myfunc(const char *pathname, const struct stat *statptr, int type);
pathname指向当前访问节点的路径名。
statptr指向当前访问节点的i-节点的结构,该结构保存有许多该文件的信息。
type给出当前访问节点的类型,在实验中可以自己定义它的含义。
myfunc()的返回值通常是0,实际上在程序4-22中它的值总是0。但是在dopath()函数中,myfunc()的返回值非0意味着终止遍历。
另外,程序4-22中用到的函数path_alloc()用于分配存放路径名的内存空间。
`#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 ");
ret=myftw(argv[1],myfunc);
ntot=nreg+ndir+nblk+nchr+nfifo+nslink+nsock;
if(ntot==0)
ntot=1;
printf(“regular files = %5d, %5.2f %%\n”,nreg,nreg
100.0/ntot );
printf(“directories = %5d, %5.2f %%\n”,ndir,ndir100.0/ntot );
printf(“block special = %5d, %5.2f %%\n”,nblk,nblk
100.0/ntot );
printf(“char special = %5d, %5.2f %%\n”,nchr,nchr100.0/ntot );
printf(“FIFOs = %5d, %5.2f %%\n”,nfifo,nfifo
100.0/ntot );
printf(“symbolic links = %5d, %5.2f %%\n”,nslink,nslink100.0/ntot );
printf(“sockets = %5d, %5.2f %%\n”,nsock,nsock
100.0/ntot );

exit(ret);

}

#define FTW_F 1
#define FTW_D 2
#define FTW_DNR 3
#define FTW_NS 4

static char *fullpath;
static size_t pathlen;

static int myftw(char *pathname,Myfunc *func)
{
fullpath=path_alloc(&pathlen);

if (pathlen <= strlen(pathname))
{
	pathlen=strlen(pathname)*2;
	if((fullpath=realloc(fullpath,pathlen))==NULL)
		err_sys("realloc failed");
}
strcpy(fullpath,pathname);
return(dopath(func));

}

static int dopath(Myfunc* func)
{
struct stat statbuf;
struct dirent *dirp;
DIR *dp;
int ret,n;
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);

n=strlen(fullpath);
if(n+NAME_MAX+2 > pathlen){
	pathlen*=2;
	if((fullpath=realloc(fullpath,pathlen))==NULL)
		err_sys("realloc failed");
}
fullpath[n++]='/';
fullpath[n]=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(&fullpath[n],dirp->d_name);
	if(ret = dopath(func)!=0)
		break;
}
fullpath[n-1]=0;
if(closedir(dp)<0)
	err_ret("can't close directory %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(“unknow type %d for pathname %s”,pathname) ;

}
return(0);

}

`
运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值