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

📄 myfind.c

📁 在linux系统中
💻 C
字号:
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <fnmatch.h>
#include <time.h>
#include <ctype.h>
#include <sys/stat.h>
char * last_char_is(const char *s, int c)//是用字符指针返回s的最后一个字符
{
        char *sret;
        if (!s)
            return NULL;
        sret  = (char *)s+strlen(s)-1;
        if (sret>=s && *sret == c) { 
                return sret;
        } else {
                return NULL;
        }
}
extern char *concat_path_file(const char *path, const char *filename)
{
        char *outbuf;
        char *lc;

        if (!path)
            path="";
        lc = last_char_is(path, '/');   //调用了last_char_is函数
        while (*filename == '/')
                filename++;
        outbuf = (char*)malloc(strlen(path)+strlen(filename)+1+(lc==NULL));
        sprintf(outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename);

        return outbuf;
}
#undef DEBUG_RECURS_ACTION                          

//这个是主要函数的定义了,注意定义的参数含义
int recursive_action(const char *fileName,
                                        int recurse, int followLinks, int depthFirst,
                                        int (*fileAction) (const char *fileName,
                                                                           struct stat * statbuf,
                                                                           void* userData),
                                        int (*dirAction) (const char *fileName,
                                                                          struct stat * statbuf,
                                                                          void* userData),
                                        void* userData)
{
        int status;
        struct stat statbuf;                                 //文件结构
        struct dirent *next;                                //目录结构

        if (followLinks == 1)                          //如果不是links
                status = stat(fileName, &statbuf);      // 调用stat把传进来要从哪开始查找的文件或目录的结构赋给statbuf
        else
                status = lstat(fileName, &statbuf);    // 调用lstat 有区别

        if (status < 0) {                            //如果要在哪查都不知道当然别查了
#ifdef DEBUG_RECURS_ACTION                     //如果定义了Recurs则 一种错误返回               
                fprintf(stderr,
                                "status=%d followLinks=%d TRUE=%d\n",
                                status, followLinks, 1);
#endif                                                        //没有则另一种返回,这里我们没定义
                printf("%s", fileName);
                return 0;
        }
                                                              //如果是要开始查找地方本身是文件或目录的链接
    //    if ((followLinks == 0) && (S_ISLNK(statbuf.st_mode))) {		if (followLinks == 0)  {
                if (fileAction == NULL)           
                        return 1;
                else                       //如果存在则直接进行匹配显示出链接
                        return fileAction(fileName, &statbuf, userData);
        }

        if (recurse == 0) {            //如果是recurse,这里我们都定义的true
             //   if (S_ISDIR(statbuf.st_mode)) {
                        if (dirAction != NULL)
                                return (dirAction(fileName, &statbuf, userData));
                        else
                                return 1;
             //   }
        }
                                   //这开始对目录进行查询 相应的文件
        if (S_ISDIR(statbuf.st_mode)) {
                DIR *dir;

                if (dirAction != NULL && depthFirst == 0) {   //开始进行查找,先用status得到diraction的状态
                        status = dirAction(fileName, &statbuf, userData);
                        if (status == 0) {        //如果没查到,则错误
                                printf("此文件不存在%s", fileName);
                                return 0;
                        } 
                }
                dir = opendir(fileName);      //把目录打开,以便在下级查
                if (!dir) {
                        printf("文件不存在:%s", fileName);
                        return 0;
                }
                status = 1;
                while ((next = readdir(dir)) != NULL) {   // 读取下级所有文件 依次匹配
                        char *nextFile;
                                              //如果碰到"."".."的文件则跳向下一个,因为没用
                        if ((strcmp(next->d_name, "..") == 0)
                                        || (strcmp(next->d_name, ".") == 0)) {
                                continue;
                        }
//对每个文件调用concat_path_file函数,该函数主要是用nextFile返回把filename和next->d_name给连接起来的值,形成所查找新值的全路径
                        nextFile = concat_path_file(fileName, next->d_name);
                        if (recursive_action(nextFile, 1, followLinks, depthFirst,
                                                fileAction, dirAction, userData) == 0) {
                             //接下来在对新的nextFile进行递归的recursive_action查找,直到找到最下一级目录           
                                status = 0;
                        }
                        free(nextFile);
                }
                closedir(dir);    //打开的就要关闭
                       //如果调用recursive存在目录,且
                if (dirAction != NULL && depthFirst == 1) {  //如果 当depthfirst 为true时的一种情况,这里也不用。
                        if (dirAction(fileName, &statbuf, userData) == 0) {
                                printf("文件不存在%s", fileName);
                                return 0;
                        }
                }
                if (status == 0)
                        return 0;
        } else {                               //如果不是目录则调用fileAction查找返回
                if (fileAction == NULL)
                        return 1;
                else
                        return fileAction(fileName, &statbuf, userData);
        }
        return 1;
}

static char *pattern;                                       //放要查找的文件名
static int fileAction(const char *fileName, struct stat *statbuf, void* junk)  
{                                       //该函数比较filename和statbuf是否匹配,是则输出,就是判断文件是否匹配
        if (pattern != NULL) {           //要查找的文件不为NULL
                const char *tmp = strrchr(fileName, '/');  //找到最后一个/后的字符,例如/home/zx/xx 则找到xx

                if (tmp == NULL)
                        tmp = fileName;           
                else
                        tmp++; //tmp指向xx 文件名或目录名
                if (!(fnmatch(pattern, tmp, FNM_PERIOD) == 0)) 
				return 1; //判断是否匹配,如果是则不输出,不是则输出
        }
        puts(fileName); //如果匹配证明查到则输出文件名 如输出xx的全路径包括了目录路径
        return 1;      //不能匹配则返回,继续查找
}
int main(int argc, char **argv)                   //主函数
{
        int dereference = 0;               //这是用来控制文件是否是连接类型的,初始为FALSE
        int i, firstopt, status = EXIT_SUCCESS;//EXIT_SUCCESS定义在stlib.h中
//完成查找功能,其中fileAction是指针函数,完成的是文件和查找文件匹配的功能,“."是指查找路径。
                if (recursive_action(".", 1, dereference, 0, fileAction,
                                        fileAction, NULL) == 0)
                        {printf("error");status = EXIT_FAILURE;}
             //如果指定了查找目录则从指定的目录开始搜索 同样调用recursive_action
             else   for (i = 1; i < firstopt; i++) {
                        if (recursive_action(argv[i], 1, dereference, 0, fileAction,
                                                fileAction, NULL) == 0)
                                status = EXIT_FAILURE;
        		}

        return status;
}




⌨️ 快捷键说明

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