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

浙公网安备 33010602011771号