📄 myfind.c
字号:
#include "apue.h"#include <dirent.h>#include <limits.h>#include <fcntl.h>#include "pathalloc.c" //pathalloc.c必须与myfind.c同一个目录#define BUFSIZE 1024 //缓冲区的大小typedef int Myfunc(const char *,const struct stat *,int);static Myfunc myfunc,myfunc2,myfunc3;static int myftw(char *,Myfunc *);static int dopath(Myfunc *);static long nreg,ndir,nchr,nblk,nfifo,nslink,nsock,ntot,ngre;//ngre用来统计文件大小<=4096的文件static long filedes,length;static char *str;int main(int argc,char *argv[]){ int ret; if(argc<2 || argc==3) err_quit("usage: myfind <pathname> or myfind <pathname> -comp <filename> or myfind <pathname> -name <str>...\n"); if(argc==2){ 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("size of reg_file<=4096B =%7ld, %5.2f %%\n",ngre,ngre*100.0/ntot); printf("dirctories =%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); } else if(argc==4 && !strcmp(argv[2],"-comp")){//实现第二个功能:查找与argv[3]内容一样的文件 if((filedes=open(argv[3],O_RDONLY))==-1) err_quit("cannot open\n"); if((length=lseek(filedes,0,SEEK_END))==-1)//用length来保存命令中argv[3]文件的大小 err_quit("lseek error\n"); ret=myftw(argv[1],myfunc2); close(filedes); } else if(argc>=4 && !strcmp(argv[2],"-name")){//实现第三个功能:查找与<str>...相同的文件 int i,j; for(i=4;i<=argc;i++){//用循环处理<str>...中的每一个 ret=strlen(argv[i-1]); if((str=(char *)malloc(ret*sizeof(char)))==NULL) err_quit("malloc error\n"); for(j=ret;argv[i-1][j]!='/' && j>=0;j--) ;//有路径,则定位到去除路径后的位置 strcpy(str,&argv[i-1][++j]);//用全局变量str来保存文件名 ret=myftw(argv[1],myfunc3); free(str); } } else err_quit("usage:myfind <pathname> -comp <filename> or myfind <pathname> -name <str>...\n"); exit(ret);}#define FTW_F 1#define FTW_D 2#define FTW_DNR 3#define FTW_NS 4static char *fullpath;static int myftw(char *pathname,Myfunc *func){ int len; fullpath=(char *)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 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++; if(statptr->st_size<=4096) ngre++; 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: ; } break; case FTW_D: ndir++; break; case FTW_DNR: ; break; case FTW_NS: ; break; default: ; } return 0;}static int myfunc2(const char *pathname,const struct stat *statptr,int type){ int filede2,len,i,flags=0; long length2; char *buf2,*buf,*path; if(type==FTW_F){//pathname是文件 if((filede2=open(pathname,O_RDONLY))==-1) return 0; if(length==statptr->st_size){//大小相同才有可能内容相同 if(lseek(filedes,0,SEEK_SET)==-1){close(filede2);return 0;} i=length/BUFSIZE;//循环的次数 buf2=(char *)malloc((BUFSIZE+1)*sizeof(char));//最后一个来放'\0' buf=(char *)malloc((BUFSIZE+1)*sizeof(char)); for(len=0;len<i;len++){ //以BUFSIZE大小逐一对两文件进行比较 if(read(filedes,buf,BUFSIZE)!=BUFSIZE){ flags=1;break;} if(read(filede2,buf2,BUFSIZE)!=BUFSIZE){flags=1;break;} buf[BUFSIZE]='\0';buf2[BUFSIZE]='\0'; if(strcmp(buf,buf2)){flags=1;break;} } if(flags){free(buf);free(buf2);close(filede2);return 0;} else if((i=length%BUFSIZE)!=0){//比较最后大小小于BUFSIZE部分 if(read(filedes,buf,i)!=i){free(buf);free(buf2);close(filede2);return 0;} if(read(filede2,buf2,i)!=i){free(buf);free(buf2);close(filede2); return 0;} buf[i]='\0';buf2[i]='\0'; if(strcmp(buf,buf2)){free(buf);free(buf2);close(filede2);return 0;} } free(buf2);free(buf); if((path=(char *)malloc(strlen(pathname)*sizeof(char)))==NULL){close(filede2); return 0;} for(len=strlen(pathname)-1;pathname[len]!='/'&&len>=0;len--) ;//查找pathname文件所在目录 for(i=0;i<=len;i++)//把文件pathname的目录名拷贝到path里 path[i]=pathname[i]; path[i]='\0'; buf2=path_alloc(&len); if(getcwd(buf2,len)==NULL){close(filede2);return 0;}//用buf2保存当前程序所在的目录 if(chdir(path)==-1){close(filede2);return 0;}//切换到文件pathname所在的目录 buf=path_alloc(&len); if(getcwd(buf,len)==NULL){close(filede2);return 0;}//用buf保存pathname所在的目录 if(chdir(buf2)==-1){close(filede2);return 0;}//切换回到程序运行所在的目录 for(i=strlen(pathname)-1;pathname[i]!='/';i--) ;//把pathname文件名提取出来 strcat(buf,&pathname[i]); printf("%s\n",buf); free(buf);free(buf2);free(path); } close(filede2); } return 0;}static int myfunc3(const char *pathname,const struct stat *statptr,int type){ int len,i; char *buf,*path,*buf2; if(type==FTW_F){ if((path=(char *)malloc(strlen(pathname)*sizeof(char)))==NULL) return 0; for(len=strlen(pathname)-1;pathname[len]!='/' && len>=0;len--) ;//查找pathname文件所在目录 if(!strcmp(str,&pathname[len+1])){//文件名相等 for(i=0;i<=len;i++)//把文件pathname的目录名拷贝到path里 path[i]=pathname[i]; path[i]='\0'; buf2=path_alloc(&len); if(getcwd(buf2,len)==NULL) return 0;//用buf2保存当前程序所在的目录 if(chdir(path)==-1) return 0;//切换到文件pathname所在的目录 buf=path_alloc(&len); if(getcwd(buf,len)==NULL) return 0;//用buf保存pathname所在的目录 if(chdir(buf2)==-1) return 0;//切换回到程序运行所在的目录 for(i=strlen(pathname)-1;pathname[i]!='/';i--) ;//把pathname文件名提取出来 strcat(buf,&pathname[i]); printf("%s\n",buf); free(buf2);free(buf);free(path); } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -