3

我正在 linux 中制作 ac 程序,用户可以在其中输入要找到的目录名称。以下是我编写的代码,但没有得到正确的输出。我正在搜索所有目录,直到找到该目录。
我只是一个初学者。

#include<unistd.h>
#include<dirent.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<errno.h>

void findDir(char *dir, char *name)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;

    if((dp = opendir(dir)) == NULL)
    {
        printf("\ncan not open directory: %s", name);
        printf("\nDescription: %s", strerror(errno));
        return;
    }

    chdir(dir);

    while(( entry = readdir(dp)) != NULL)
    {
        lstat( entry->d_name, &statbuf);
        if(S_ISDIR( statbuf.st_mode))
        {
            if( strcmp(name,entry->d_name) == 0)
            {
                printf("Dir found");
                return;
            }
            findDir(entry->d_name, name);
        }
    }
    chdir("..");
    closedir(dp);
}

void main(int argc, char *argv[])
{
    if( argc != 2 )
    {
        printf("Error");
    }
    else
    {
        findDir("/home", argv[1]);
    }
}

请帮忙!!在将Documents作为参数时,我得到了以下输出。实际上程序是无限的,我反复得到以下输出。这只是输出的一小部分。

打不开目录:Documents
说明:打开的文件太多
打不开目录:Documents说明:打开的文件太多 打不开目录:Documents
说明:打开的文件 太多Dir found

4

4 回答 4

5

问题是readdir()不能入。它依赖于一个内部缓冲区,当你递归时,它会被覆盖。如果您使用的是 POSIX 标准,您可以尝试readdir_r哪个是可重入的。

或者,您可以在开始递归之前将目录读入列表,然后一次处理列表中的项目。这样,您在尝试深入目录树的下一级之前已经阅读了整个目录,并且当前级别的条目不会因更深层次的覆盖而丢失。

于 2013-05-02T17:53:27.907 回答
2

您将在此处遇到的另一个问题(也是现在可能对您影响最大的问题)是特殊目录条目.并将..显示在opendir()/的结果中readdir()。您将需要使用以下内容检查并跳过这两个:

if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
    continue;
于 2013-05-02T18:05:33.277 回答
0

我快速浏览了一下。这里有一些建议。

  • 调试时,要么在调试器中单步执行,要么至少放置一些打印语句以查看实际发生的情况。我在遍历目录的循环中放入了一个printf()循环,发现它立即尝试访问..目录,因此它/home永远离开并循环。

  • 所以,在你的循环中,在你做任何其他事情之前,测试看看是否entry->d_name"."or "..",如果是,跳过那个目录条目(你可以只使用continue关键字)。

  • 确保closedir(dp);在函数返回之前调用。例如,当您的代码打印 message 时can not open directory:,您的函数会在不关闭目录的情况下返回。顺便说一句,您应该打印entry->d_name该错误消息,而不是name.

该错误Too many open files是因为您的循环正在跟随..,因此它永远不会停止,并且它找到了大量无法打开的目录,因此closedir()在错误退出时未调用的代码意味着越来越多的目录处于打开状态。

  • 你的程序会在找到目标目录后继续运行!它会打印一条消息,但会继续。您可以修改您的函数findDir()以返回一个代码,说明它是否找到了目标,并在这种情况下让您的程序停止。
于 2013-05-02T18:07:06.620 回答
0

您最好使用nftw(3)库函数,它能够递归地遍历文件树。

如果你不被允许使用它,你至少可以研究它的源代码,例如从MUSL libc文件src/misc/nftw.c中我发现它非常易读。

顺便说一句,您对代码的调用lstat是错误的,您需要构建整个文件路径。

您需要gdb在程序上使用调试器。您可能还想使用strace它来了解它正在执行哪些系统调用(并且strace-ing 一些find命令也会教给您很多东西)。

于 2013-05-02T20:08:32.107 回答