【问题标题】:C - Scandir only fill namelist with foldersC - Scandir 只用文件夹填充名单
【发布时间】:2015-01-17 09:01:03
【问题描述】:

如何使用 scandir,以便它只用文件夹填充我的 struct dirent ** 名称列表?

【问题讨论】:

    标签: c filter scandir


    【解决方案1】:

    您可以通过提供过滤器函数来过滤要列出的实体,如果要包含在列表中的文件应该返回一个非零值。

    很遗憾,dirent 结构体的成员并不会告诉你是否有目录(尽管your system might include a type field),所以你必须使用其他方式来查找目录,例如stat

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <dirent.h>
    
    int filter_dir(const struct dirent *e)
    {
        struct stat st;
    
        stat(e->d_name, &st);
        return (st.st_mode & S_IFDIR);
    }
    

    您也可以尝试在名称上调用opendir 并检查是否成功。 (不过成功了别忘了关闭哦。)

    这适用于当前目录,因为名称不包括路径。过滤器也不提供用于传递额外数据的插槽,因此您可以做的最好的事情是定义一个保存路径的全局变量,并且您必须事先设置。

    这是一个带有包装函数的实现,scandir_dir

    #include <stdlib.h>
    #include <stdio.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <dirent.h>
    
    static const char *filterdir;
    
    static int filter_dir(const struct dirent *e)
    {
        char buf[NAME_MAX];
        struct stat st;
    
        if (filterdir) {
            snprintf(buf, sizeof(buf), "%s/%s", filterdir, e->d_name);    
            stat(buf, &st);
        } else {    
            stat(e->d_name, &st);
        }
        return (st.st_mode & S_IFDIR);
    }
    
    int scandir_dir(const char *path, struct dirent ***namelist)
    {
        int n;
    
        filterdir = path;
        n = scandir(path, namelist, filter_dir, alphasort);
        filterdir = NULL;
    
        return n;
    }
    
    int main()
    {
        struct dirent **namelist;
        int n;
    
        n = scandir_dir("/some/dir", &namelist);
    
        if (n < 0) {
            perror("scandir");
        } else {
            int i;
    
            for (i = 0; i < n; i++) {
                printf("%s\n", namelist[i]->d_name);
                free(namelist[i]);
            }
            free(namelist);
        }
    
        return 0;
    }
    

    【讨论】:

    • filter_dir 被声明为静态是否有原因?
    • 是的,@ruisen:filterdir 是私有状态,必须可以从过滤函数和设置它的函数访问。将其设为static 将无法从其他编译单元访问它。 (不过,在这个小示例程序中,一切都在一个文件中,这无关紧要。)
    • 感谢您的回复!如果这个函数被实现为类成员函数,为什么需要将其设为静态?我在代码库中看到一条评论说,因为它调用 scandir,所以调用函数和过滤函数都必须是静态的 - 但我似乎找不到任何原因。
    • 这是 C 中的一个答案,其中 static 函数是当前编译单元私有的,即源文件。它与 C++ 或类似语言中的 static 类成员没有任何关系,它们是不作用于类实例的函数。另外,你在说什么代码库?我有一种感觉,你以我的回答为借口,把我拖入了一个完全不相关的讨论中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    相关资源
    最近更新 更多