⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 3.c

📁 掌握与文件和目录树有关的系统调用和库函数。
💻 C
字号:
//main函数:

int  main(int argc, char *argv[])
{
	int	tag = 0;
	int	ret,i;
	if (argc == 4 && !strcmp(argv[2],"-comp"))
	{	
		tag = 1;
		if((fp = open(argv[3],O_RDONLY))<0)    //打开要进行比较的文件 
                        err_sys("open file error");
		filelength=lseek(fp,0,SEEK_END);
		buf=(char *)malloc((filelength)*sizeof(char));
                lseek(fp,0,SEEK_SET);
		if(read(fp,buf,filelength)<0)   //将该文件的内容读入到一个数组中保存 
			err_sys("file read error");
		ret = myftw(argv[1],myfunc2);
		free(buf);
        }
        if (argc >= 4 && !strcmp(argv[2],"-name") )
	{
		tag = 1;
		filenum=argc-3;    //统计要进行查找的文件的数量 
		for(i=0;i<filenum;++i) 
			dirfile[i] = path_alloc(NULL);
		for(i=0;i<filenum;++i)    //将要进行比较的文件的名字保存到一个数组中 
			strcpy(dirfile[i],argv[3+i]);
		ret = myftw(argv[1],myfunc3);
	}
	if (argc == 2)
	{
		tag = 1;
		ret = myftw(argv[1],myfunc);
		if((ntot=nreg+ndir+nblk+nchr+nfifo+nslink+nsock) ==0 )
			ntot = 1;		/* avoid divide by 0; print 0 for all counts */
		printf("\nregular 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);
		printf("f_size<=4096B  = %7ld, %5.2f %%\n", nb4096,nb4096*100.0/nreg);  //输出文件大小小于4096的文件的//数量和所占百分比 
	}
 	if( !tag )
		err_quit("usage:  myfind  <pathname> [-comp<filename>|-name<str>...]");
	printf("\n");
	exit(0);
}

//dopath函数

static int					/* we return whatever func() returns */
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));	/* stat error */
	if (S_ISDIR(statbuf.st_mode) == 0)
		return(func(fullpath, &statbuf, FTW_F));	/* not a directory */
		if ( (ret = func(fullpath, &statbuf, FTW_D)) != 0)
		return(ret);
	ptr = fullpath + strlen(fullpath);	/* point to end of fullpath */
	if(*(ptr-1)!='/')          //判断路径中是否已经含有‘/’,若有则不加‘/’
		*ptr++ = '/';
	*ptr = 0;
	if ( (dp = opendir(fullpath)) == NULL)
		return(func(fullpath, &statbuf, FTW_DNR));
										/* can't read directory */
	while ( (dirp = readdir(dp)) != NULL) {
		if (strcmp(dirp->d_name, ".") == 0  ||
		    strcmp(dirp->d_name, "..") == 0)
				continue;		/* ignore dot and dot-dot */
		strcpy(ptr, dirp->d_name);	/* append name after slash */
		strcpy(filename,dirp->d_name);
		if ( (ret = dopath(func)) != 0)		/* recursive */
			break;	/* time to leave */
	}
	ptr[-1] = 0;	/* erase everything from slash onwards */
	if (closedir(dp) < 0)
		err_ret("can't close directory %s", fullpath);
	return(ret);
}
//3个操作函数:

static int  myfunc(const char *pathname, const struct stat *statptr, int type)
{
	struct stat statfile;
	switch (type) {
	case FTW_F:
		switch (statptr->st_mode & S_IFMT) {
		case S_IFREG:	nreg++;	
				stat(pathname,&statfile);
				if(statfile.st_size <= 4096)   //判断文件大小是否小于4096B,若小于则进行记数加1 
		 		    nb4096++; 
				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);
					/* directories should have type = FTW_D */
		}
		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("unknown type %d for pathname %s", type, pathname);
	}
	return(0);
}

static int  myfunc2(const char *pathname,const struct stat *statptr, int type)
{
	char *readfile,*path;
	int f;
	const size_t size=200;
	char T_path[size];
	if(type == FTW_F)
	{
		if(statptr->st_size != filelength)  //先判断文件大小是否相同 
			return(0);
		if((f=open(pathname,O_RDONLY))<0)   //打开要读取的文件 
			err_sys("open file error");
		readfile=(char *)malloc(filelength*sizeof(char));
		if(read(f,readfile,filelength)<0)  //将该文件的内容写入到一个数组中去 
			err_sys("read file error");
		readfile[filelength]='\0';
		if(strcmp(buf,readfile) == 0)  //比较文件内容是否相同 
		{
			printf("\n");
			path=getcwd(T_path,size);  //获得当前工作程序的绝对路径 
			all_path(path,pathname);   //输出该文件所在的绝对路径 
		}
		free(readfile); 
	}
	return(0);

}

static int  myfunc3(const char *pathname,const struct stat *statptr,int type)
{
	int i;
	const size_t size=200;
	char A_path[size];
	if(type==FTW_F)
	{
		getcwd(A_path,size);   //获得当前工作程序的绝对路径 
		for(i=0;i<filenum;++i)   //遍历查找是否该文件与所给文件中的一个名字相同 
			if(!strcmp(dirfile[i],filename))
			{
				printf("\n");
				all_path(A_path,pathname);
			}
	}
	return(0);
}

//输出绝对路径的函数:

static int  all_path(char *A_path,const char *pathname)
{
	char *path;
	path = path_alloc(NULL);
	strcpy(path,pathname);
	int i=0,j=strlen(A_path);
	while(*path=='.')
	{
		i++;
		if(path[i]=='/'&&i==2)   //判断输入的路径中是否含有向上退一级的符号 ../ 若有则对两个路径进行相应的处理 
		{
			path=path+i+1;  //将指针指向 . . / 后面的第一个地址 
			do{
				*(A_path+j-1)='\0';  //将当前工作路径退一个文件夹 
				--j;
			} while(*(A_path+j-1)!='/');
            if(i==1) //若路径中含有 . ,则表示为当前文件夹,将path指向下一个地址 
				 path++;
			i=0; //重新记数判断 
		}
	}
	
	printf("%s\n",strcat(A_path,path));
	return(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -