目录操作

目录操作


基本概念

目录也是一种文件,因此操作流程与普通文件类似,有诸如打开、关闭、定位等概念,但目录是一种特殊的文件,目录存储的数据的最小单位并不是字符,而是目录项(条目)。这使得目录跟普通文件又有区别。

在 Linux 文件系统的经典结构中,目录不同于文件夹目录的本质是索引,文件夹的本质是容器。在 Linux 中,目录有几个要点:

  • 整个分区被分成两部分,一部分称为i 节点域,另一部分称为数据域
  • i 节点域记录的是整个分区的基本信息,包括分区可用空间和已用空间的管理信息
  • 数据域存储文件实际内容数据
  • 每一个文件(包括目录本身)拥有一个唯一的标识,称为 i 节点号,分区使用 i 节点号管理并索引所有的文件
  • 目录所存储的数据单元是目录项,目录项指的是结构体 struct dirent{},其内部保存的是文件的名称、i 节点号等基本信息,不包含文件具体内容
  • 任何一个目录至少包含两个目录项:...
    • . 代表当前目录
    • .. 代表上一级目录
    • 如果本目录就是根目录,那么 .. 也代表本级目录

基础 API 接口

① 创建、删除目录

示例代码:

int main(void)
{
    // 在家目录下创建一个空目录
    mkdir("/home/gec/a", 0755);

    // 将空目录删除(以下两条语句等价)
    rmdir("/home/gec/a");
    remove("/home/gec/a");
}

② 打开目录

头文件:
    #include <sys/types.h>
    #include <dirent.h>
函数原型:
    DIR *opendir(const char *name);
参数分析:
    name --> 目标目录的完整路径
返回值:
    成功 返回目录流
    失败 返回NULL ,并设置错误码 

③ 读取目录项

头文件:
    #include <dirent.h>

函数原型:
   struct dirent *readdir(DIR *dirp);

参数分析:
    dirp --> 需要读取的目录流指针
返回值:
    成功 得到目录项的结构体地址(一个条目)
    失败 返回NULL

关于目录项的结构体:

struct dirent {
    ino_t          d_ino;       /* inode编号 */
    off_t          d_off;       /* 不是偏移量;具体含义取决于文件系统 */
    unsigned short d_reclen;    /* 本记录的长度 */
    unsigned char  d_type;      /* 文件类型;不是所有文件系统都支持 */
    char           d_name[256]; /* 以空字符结尾的文件名 */
};

d_type:
    DT_BLK      This is a block device.
    DT_CHR      This is a character device.
    DT_DIR      This is a directory.
    DT_FIFO     This is a named pipe (FIFO).
    DT_LNK      This is a symbolic link.
    DT_REG      This is a regular file.
    DT_SOCK     This is a UNIX domain socket.
    DT_UNKNOWN  The file type could not be determined.

④ 关闭目录

#include <sys/types.h>
#include <dirent.h>

int closedir(DIR *dirp);

目录遍历安全模板(递归)

int scan_dir(const char *path, void (*action)(const char *))
{
    DIR *dir = opendir(path);
    if (!dir) return -1;

    struct dirent *ent;
    while ((ent = readdir(dir))) {
        if (strcmp(ent->d_name, ".") == 0 ||
            strcmp(ent->d_name, "..") == 0) continue;

        char full[PATH_MAX];
        snprintf(full, sizeof(full), "%s/%s", path, ent->d_name);

        if (ent->d_type == DT_DIR) {
            scan_dir(full, action);          // 递归
        } else {
            action(full);                    // 处理文件
        }
    }
    closedir(dir);
    return 0;
}
posted @ 2025-11-08 15:45  林明杰  阅读(5)  评论(0)    收藏  举报