在 Linux C 开发中文件与目录操作是高频场景但相关结构体繁多容易混淆。本文对 5 个核心结构体进行系统梳理帮助开发者快速掌握其用途与区别避免踩坑。我在做 Linux 嵌入式开发时经常和这几个结构体打交道踩过不少坑。今天我把它们的核心知识点和避坑指南整理出来希望能帮到大家。1.struct dirent目录项结构定义#include dirent.h作用存储目录中单个文件的元信息文件名、inode 号等。典型流程opendir() → readdir() → closedir()核心成员d_name文件名d_ino文件 inode 号#include dirent.h #include stdio.h int main() { DIR *dir opendir(.); struct dirent *ent; while ((ent readdir(dir)) ! NULL) { printf(%s\n, ent-d_name); } closedir(dir); return 0; }2.struct stat文件属性结构定义#include sys/stat.h作用获取文件的详细属性大小、类型、权限、时间戳等。典型函数stat()/lstat()/fstat()核心成员st_size文件大小字节st_mode文件类型与权限需配合掩码S_IFMT、0777使用例如S_ISREG(st_mode)判断是否为普通文件st_mtime最后修改时间#include stdio.h #include sys/stat.h #include unistd.h int main() { struct stat st; if (stat(test.txt, st) 0) { printf(Size: %ld bytes\n, st.st_size); if (S_ISREG(st.st_mode)) { printf(Regular file\n); } printf(Permissions: %o\n, st.st_mode 0777); } else { perror(stat failed); } return 0; }3.DIR目录句柄定义#include dirent.h作用代表一个已打开的目录作为遍历目录的操作句柄。典型流程opendir()打开目录 →readdir()读取目录项 →closedir()关闭。注意DIR是不透明类型内部结构由系统实现不应直接访问。#include dirent.h #include stdio.h #include string.h int main() { // 1. 打开当前目录获取DIR句柄 DIR *dir_ptr opendir(.); if (dir_ptr NULL) { // 必加错误检查贴近实际开发 perror(opendir failed); return 1; } struct dirent *ent_ptr; // 2. 循环读取目录项直到readdir返回NULL while ((ent_ptr readdir(dir_ptr)) ! NULL) { // 过滤.和..目录避免无意义输出实际开发常用技巧 if (strcmp(ent_ptr-d_name, .) 0 || strcmp(ent_ptr-d_name, ..) 0) { continue; } printf(文件名%s | inode号%ld\n, ent_ptr-d_name, ent_ptr-d_ino); } // 3. 关闭DIR句柄避免资源泄漏 closedir(dir_ptr); return 0; }4.FILE文件流句柄定义#include stdio.h作用标准 C 库提供的文件操作句柄支持缓冲 I/O。典型流程fopen()打开文件 →fread()/fwrite()读写 →fclose()关闭。与文件描述符的关系可通过fileno(FILE*)获取底层文件描述符用于更底层的操作。#include stdio.h #include string.h int main() { // 1. 打开文件w读写模式不存在则创建存在则清空 FILE *fp fopen(test.txt, w); if (fp NULL) { // 必加错误检查 perror(fopen failed); return 1; } // 2. 写入数据带缓冲实际开发常用fputs/fprintf const char *content Linux C FILE结构体示例\n; fputs(content, fp); // 3. 移动文件指针到开头准备读取 fseek(fp, 0, SEEK_SET); // 4. 读取数据并打印 char buf[1024] {0}; fgets(buf, sizeof(buf), fp); printf(读取到的内容%s, buf); // 5. 可选获取底层文件描述符对接Linux系统调用 int fd fileno(fp); printf(FILE对应的文件描述符%d\n, fd); // 6. 关闭文件释放缓冲句柄 fclose(fp); return 0; }5.glob_t路径匹配结构定义#include glob.h作用用于批量匹配文件路径如*.c、/usr/bin/*。典型函数glob()执行匹配 →globfree()释放资源。核心成员gl_pathv匹配到的路径数组gl_pathc匹配到的路径数量#include glob.h #include stdio.h int main() { glob_t g; if (glob(./*.c, 0, NULL, g) 0) { for (size_t i 0; i g.gl_pathc; i) { printf(%s\n, g.gl_pathv[i]); } } globfree(g); return 0; }核心区别速查表结构体核心用途关联函数典型场景struct dirent存储目录项信息readdir()遍历目录、列出文件名struct stat获取文件属性stat()/lstat()查文件大小、类型、权限DIR目录操作句柄opendir()/closedir()打开、遍历目录FILE文件流操作fopen()/fclose()读写普通文件带缓冲glob_t批量路径匹配glob()/globfree()批量查找.c文件等风险提示必看线程安全在多线程环境中使用DIR和FILE句柄时需要注意线程安全避免并发读写导致数据混乱。路径安全使用glob()函数时要注意路径匹配的安全性避免因用户输入导致的路径遍历漏洞。资源泄漏所有打开的句柄DIR*、FILE*都必须在使用后正确关闭glob_t必须用globfree()释放否则会造成资源泄漏长期运行的程序尤其需要注意。你在 Linux C 文件操作中还遇到过哪些结构体相关的坑欢迎在评论区分享你的经验我们一起交流进步。水平有限欢迎大家交流指正共同进步。