如何使用c语言在Linux中查找目录?

3

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

#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
描述:文件打开过多


1
你能编辑问题并添加你得到的输出吗? - Dan Pichelman
是的,请在输出中添加并在strcmp之前的name,entry->d_name上添加printf以进行调试。 - Sudhee
4个回答

5
问题在于readdir()不是可重入的。它依赖于一个内部缓冲区,当递归时,该缓冲区被覆盖。如果您使用POSIX标准,可以尝试readdir_r,它是可重入的。
或者,您可以在开始递归之前将目录读入列表中,然后逐个处理列表中的条目。这样,在尝试深入目录树的下一级之前,您已经读取了整个目录,并且当前级别的条目不会在更深层次上被覆盖。

2

在这里你会遇到另一个问题(也是目前最影响你的问题),特殊的目录项...将出现在opendir()/readdir()的结果中。你需要使用以下类似的方法检查并跳过这两个目录项:

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

0

我快速地看了一下这个代码。 这是我的一些建议。

  • 在调试时,可以使用调试器逐步执行,或者至少添加一些打印语句来查看实际发生的情况。 我在遍历目录的循环中加入了一个printf()语句,并发现它立即尝试访问..目录,因此导致/home目录无限循环。

  • 所以,在你的循环中,在执行其他操作之前,先判断entry->d_name是否为".""..",如果是的话,跳过该目录(可以使用continue关键字)。

  • 确保在函数返回之前调用closedir(dp);。例如,当你的代码打印can not open directory:消息时,你的函数没有关闭目录。 另外,你应该在错误消息中打印entry->d_name,而不是name

错误 Too many open files 是因为您的循环遵循 ..,所以它永远不会停止,并且它找到了许多无法打开的目录,因此代码在错误退出时没有调用 closedir(),这意味着越来越多的目录保持打开状态。

  • 在找到目标目录后,您的程序将继续运行! 它会打印一条消息但仍然继续。 您可以修改函数 findDir() 以返回一个代码,指示它是否找到了目标,如果是,则使程序停止。

我尝试了一下,虽然它已经停止无限循环,但仍然没有得到所需的结果。以下是输出:./a.out Documents 无法打开目录:Documents 描述:打开文件太多。 - Pratik Singhal

0

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

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

顺便说一句,在你的代码中,调用lstat是错误的,你需要构造整个文件路径。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接