【发布时间】:2015-01-17 09:01:03
【问题描述】:
如何使用 scandir,以便它只用文件夹填充我的 struct dirent ** 名称列表?
【问题讨论】:
如何使用 scandir,以便它只用文件夹填充我的 struct dirent ** 名称列表?
【问题讨论】:
您可以通过提供过滤器函数来过滤要列出的实体,如果要包含在列表中的文件应该返回一个非零值。
很遗憾,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;
}
【讨论】:
filterdir 是私有状态,必须可以从过滤函数和设置它的函数访问。将其设为static 将无法从其他编译单元访问它。 (不过,在这个小示例程序中,一切都在一个文件中,这无关紧要。)
static 函数是当前编译单元私有的,即源文件。它与 C++ 或类似语言中的 static 类成员没有任何关系,它们是不作用于类实例的函数。另外,你在说什么代码库?我有一种感觉,你以我的回答为借口,把我拖入了一个完全不相关的讨论中。