📄 3.c
字号:
#include "sys/types.h"
#include "sys/stat.h"
#include "dirent.h"
#include "limits.h"
#include "ourhdr.h"
#include "unistd.h"
#include "fcntl.h"
#include "pathalloc.c"
#include "error.c"
/* function type that is called for each filename */
typedef int Myfunc(char *, const struct stat *, int);
static Myfunc myfunc;
static Myfunc myfunc1;
static Myfunc myfunc2;
static int myftw(char *, Myfunc *);
static int dopath(Myfunc *);
static int intype; //标记输入命令的类型
static char *buf,*buf1;
static struct stat stabuf;
static char **p;
static char *pargv; //指向要进行比较的文件路径
static char *abspath; //存放当前工作目录的绝对路径
int filesnum;
static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot,nf4k=0;//nf4k存放文件长度小于4096字节的文件个数
int
main(int argc, char *argv[])
{
int ret;
int intype;
if(argc==2) //输入类型判断
intype=0;
else if(strcmp(argv[2],"-comp")==0){ //若为comp情况
pargv=argv[3]; //指向要进行比较的文件路径
if(lstat(argv[3],&stabuf)<0) //取要进行比较的文件(argv[3])的信息
err_ret("stat error for %s",argv[3]);
buf=(char *)malloc(stabuf.st_size *sizeof(char)); //用于读入argv[3]文件
buf1=(char *)malloc(stabuf.st_size *sizeof(char)); //用于存放与之进行比较的文件
int fd;
if((fd=open(argv[3],O_RDONLY))==-1) //打开argv[3]文件
err_ret("can not open file: %s",argv[3]);
if(read(fd,buf,stabuf.st_size)<0) //读入argv[3]文件
err_ret("can not read file: %s",argv[3]);
intype=1;
}
else if(strcmp(argv[2],"-name")==0){ //若为name情况
filesnum=argc-3; //存要进行比较的文件名个数
p=(char **)malloc(filesnum*sizeof(char));//保存文件名
int i;
for(i=3;i<argc;i++)
p[i-3]=argv[i];
intype=2;
}
else{
printf("input fomat error!"); //输入格式错误
return;
}
chdir(argv[1]); //当前工作目录转向给定的目录
int size;
abspath=path_alloc(&size); //存放当前工作目录的绝对路径
if(getcwd(abspath,size)==NULL)//取当前工作目录
err_sys("getcwd failed!");
char *pp;
pp="."; //pathname为当前工作目录即.
if(intype==0){
ret = myftw(pp, myfunc);
ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
if (ntot == 0)
ntot = 1; /* avoid divide by 0; print 0 for all counts */
//输出相关信息
printf("regular files = %7ld, %5.2f %% %5.2f %%\n", nreg,nreg*100.0/ntot,nf4k*100.0/nreg);//nf4k为文件大小小于4096字节的文件数
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);
}
else if(intype==1)
ret=myftw(pp,myfunc1);
else
ret=myftw(pp,myfunc2);
exit(ret);
}
/*
* Descend through the hierarchy, starting at "pathname".
* The caller's func() is called for every file.
*/
#define FTW_F 1 /* file other than directory */
#define FTW_D 2 /* directory */
#define FTW_DNR 3 /* directory that can't be read */
#define FTW_NS 4 /* file that we can't stat */
static char *fullpath; /* contains full pathname for every file */
static int /* we return whatever func() returns */
myftw(char *pathname, Myfunc *func)
{
int len;
fullpath = path_alloc(&len); /* malloc's for PATH_MAX+1 bytes */
/* (Figure 2.15) */
strncpy(fullpath, pathname, len); /* protect against */
fullpath[len-1] = 0; /* buffer overrun */
return(dopath(func));
}
/*
* Descend through the hierarchy, starting at "fullpath".
* If "fullpath" is anything other than a directory, we lstat() it,
* call func(), and return. For a directory, we call ourself
* recursively for each name in the directory.
*/
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) /* 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 each filename in the directory.
*/
if ((ret = func(fullpath, &statbuf, FTW_D)) != 0)
return(ret);
ptr = fullpath + strlen(fullpath); /* point to end of fullpath */
*ptr++ = '/';
*ptr = 0;
if ((dp = opendir(fullpath)) == NULL) /* can't read directory */
return(func(fullpath, &statbuf, FTW_DNR));
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 */
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);
}
static int
myfunc (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)
nf4k++;
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; /* 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);
break;
}
return(0);
}
static int
myfunc1(char *pathname, const struct stat *statptr, int type) //若pathname为const则不能该
{
char *t;
switch (type) {
case FTW_F:
if(stabuf.st_size==statptr->st_size){ //若两文件的大小相同
int fd;
if((fd=open(pathname,O_RDONLY))==-1) //打开文件
err_ret("can not open file: %s",pargv);
if(read(fd,buf1,stabuf.st_size)<0) //读入内容
err_ret("can not read file: %s",pargv);
/*if内容相同输出路径,close文件*/
if(strcmp(buf,buf1)==0){ //若两文件内容相同
if(strcmp(abspath,"/")!=0) //若当前工作目录为根目录
printf("%s",abspath); //不输出当前工作目录的绝对路径
printf("%s\n",pathname+1); //输出符合条件的文件的绝对路径
}
close(fd); //关闭打开的文件
}
break;
case FTW_D:
break;
case FTW_DNR:
break;
case FTW_NS:
break;
default:
break;
}
return(0);
}
static int
myfunc2 (char *pathname, const struct stat *statptr, int type)
{
char *t;
switch (type) {
case FTW_F:
t=pathname + strlen(pathname);
while(*t!='/')
t--;
t++; //t指向pathname指向的文件名
int i;
for(i=0;i<filesnum;i++){ //分别与给定的文件名比较
if(strcmp(t,p[i])==0){ //若文件名相同
if(strcmp(abspath,"/")!=0) //若当前工作目录为根目录
printf("%s",abspath); //不输出当前工作目录的绝对路径
printf("%s\n",pathname+1); //输出符合条件的文件的绝对路径
}
}
break;
case FTW_D:
ndir++;
break;
case FTW_DNR:
break;
case FTW_NS:
break;
default:
break;
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -