Linux下统计某个目录文件数目

这篇文章的所有代码来自《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;
}

















你可能感兴趣的:(linux,struct,null,Path,hierarchy,Sockets)