在 Linux 下使用 readdir()(或 readdir_r())遍历目录时,readdir 本身并不支持过滤条件,只能在拿到每个目录项(struct dirent)后,在用户态自己判断、过滤。
下面按常见场景说明如何“过滤”。
#include <dirent.h>
#include <stdio.h>
DIR *dir = opendir("/path");
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
⚠️ 注意:readdir 会返回:
...while ((entry = readdir(dir)) != NULL) {
// 跳过 . 和 ..
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
// 只处理 .txt 文件
if (strstr(entry->d_name, ".txt"))
printf("%s\n", entry->d_name);
}
d_type 可判断类型(不是所有文件系统都支持)
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG) // 普通文件
printf("FILE: %s\n", entry->d_name);
else if (entry->d_type == DT_DIR) // 目录
printf("DIR : %s\n", entry->d_name);
}
常见类型:
DT_REG:普通文件DT_DIR:目录DT_LNK:符号链接DT_UNKNOWN:未知(需 stat)当 d_type == DT_UNKNOWN 时:
#include <sys/stat.h>
struct stat st;
char path[256];
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
if (stat(path, &st) == 0) {
if (S_ISREG(st.st_mode)) // 普通文件
printf("REG: %s\n", entry->d_name);
if (S_ISDIR(st.st_mode)) // 目录
printf("DIR: %s\n", entry->d_name);
}
scandir(自带过滤函数)struct dirent **namelist;
int n = scandir(".", &namelist, NULL, alphasort);
for (int i = 0; i < n; i++) {
printf("%s\n", namelist[i]->d_name);
free(namelist[i]);
}
free(namelist);
自定义过滤:
int filter(const struct dirent *e) {
return strncmp(e->d_name, "log", 3) == 0;
}
scandir(".", &namelist, filter, alphasort);
#include <regex.h>
regex_t reg;
regcomp(®, ".*\\.conf$", 0);
if (regexec(®, entry->d_name, 0, NULL, 0) == 0)
printf("%s\n", entry->d_name);
regfree(®);
| 需求 | 推荐方式 |
|---|---|
| 简单文件名 | strstr / strcmp |
| 文件类型 | d_type + stat |
| 内置过滤 | scandir |
| 复杂规则 | regex |
✅ readdir 本身不过滤,只能“读出来再判断”
如果你有具体场景(比如:只遍历文件、递归目录、隐藏文件、权限过滤),可以告诉我,我给你写完整示例。