递归搜索目录以查找文件

时间:2017-04-12 14:31:09

标签: c recursion

我正在尝试以递归方式在目录中搜索文件,如果文件与给定文件匹配,则输出该文件:

static int *search(char *path, const char *request, int depth, bool verbose)
{
    DIR *dir;
    struct dirent *ent;
    char *start_dir = strcmp(path, "/") == 0 ? "root" : path;

    printf("\nStarting in '%s' directory..\n\n", start_dir);

    if ((dir = opendir(path)) != NULL)
    {
        while ((ent = readdir(dir)) != NULL)
        {
            if (verbose == true)
            {
                printf("Searching directory %s for file %s\n", ent->d_name, request);
            }
            if (ent->d_type == DT_DIR)
            {
                if ((strlen(path) + strlen(ent->d_name) + 1) > PATH_MAX)
                {
                    puts("Path to long, cannot continue..");
                }
                else
                {
                    if (ent->d_name == DT_DIR && strcmp(ent->d_name, ".") != 0 &&
                            strcmp(ent->d_name, "..") != 0 )
                    {
                        printf("%s\n", ent->d_name);
                    }
                }
            }
        }
    }
    return 0;
}

这将有效,但不会输出目录中的文件或目录。例如:

@ubuntu:~/bin/c/find-files$ ./utilis test / -V
Initialized to search for file: 'test'..
Starting in 'root' directory..

Searching directory vmlinuz.old for file test
Searching directory boot for file test
Searching directory home for file test
Searching directory libx32 for file test
Searching directory lib32 for file test
Searching directory lib64 for file test
Searching directory initrd.img for file test
Searching directory srv for file test
Searching directory usr for file test
Searching directory . for file test
Searching directory cdrom for file test
Searching directory tmp for file test
Searching directory initrd.img.old for file test
Searching directory bin for file test
Searching directory .. for file test
Searching directory proc for file test
Searching directory lib for file test
Searching directory var for file test
Searching directory dev for file test
Searching directory sys for file test
Searching directory media for file test
Searching directory root for file test
Searching directory snap for file test
Searching directory run for file test
Searching directory sbin for file test
Searching directory opt for file test
Searching directory lost+found for file test
Searching directory mnt for file test
Searching directory vmlinuz for file test
Searching directory etc for file test

如何重构此函数以便在所有目录和子目录中递归搜索给定的文件名?

1 个答案:

答案 0 :(得分:0)

正如许多人的评论中已经指出的那样。丢失的递归调用(函数调用自身)不会递归您的代码。你有很多错误。不检查各种系统调用的错误,忘记关闭目录流。我不知道您希望通过各种参数int depthbool verbose实现什么目标。但这是寻找特定文件并在成功时返回0 --> EXIT_SUCCESS并在失败时返回1 -->EXIT_FAILURE的另一种方式。

使用系统调用时会出现各种错误,有些设置errnos,这对于查看它们并打印到STDERR非常重要

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>


#define DEBUG 1

static int search(char *path,const char *file){
    DIR *dir;
    char *slash = "/";

    int ret = 1;

    struct dirent *entry;
//checking if it failed to open and report errors to STDERR
    if((dir = opendir(path)) == NULL){
        fprintf(stderr,"opendir: %s\n",strerror(errno));
        return EXIT_FAILURE;
    }

    while ((entry = readdir(dir))){

//if is . or .. we continue to prevent winging back and forth

        if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0)
            continue;

//we check if the path has already a / if not we add one

        int length = strlen(path);

        if(path[length-1] != '/'){
            slash = "/";
        }

        length += strlen(entry->d_name)+2;
        char *newpath = malloc(length);
        if (!newpath){
            fprintf(stderr,"malloc: %s\n",strerror(errno));
            break;
        }

        snprintf(newpath,length,"%s%s%s",path,slash,entry->d_name);

        if(strcmp(entry->d_name,file) ==0){
#if DEBUG
            printf("Was found here %s\n",newpath);
#endif
            ret =  EXIT_SUCCESS;
            break;
        }
        //checking if is a directory to do a recursive call
        // using DT_DIR to avoid the use of lstat or stat
        // if not directory we free the memory and move on
        if(entry->d_type == DT_DIR)
            search(newpath,file);
        else{
            free(newpath);
            continue;
        }

        free(newpath);
    }
    if(closedir(dir) != 0){
        fprintf(stderr,"closedir: %s\n",strerror(errno));
        return EXIT_FAILURE;
    }

    return ret;

}


int main() {


    char *file = "algo.c";

    int ret = search("/",file);

    printf("%d The file %s was %s\n",ret,file,(ret == 0 ? "found":"not found"));



    return 0;
}

将DEBUG设置为1

  

在这里找到/Users/addodennis/CLionProjects/BluePrint/algo.c

     

找到了algo.c文件

将DEBUG设置为0

  找到文件algo.c