获取目录信息和获取文件信息差不多,起初Unix 的设计就将目录定义为一种特殊的文件
struct __dirstream { void *__fd; char *__data; int __entry_data; char *__ptr; int __entry_ptr; size_t __allocation; size_t __size; __libc_lock_define (, __lock) }; typedef struct __dirstream DIR;
在这不过多讨论DIR内部结构体的成员,只需要知道这个结构体也是保存了当前正在被读取的目录的有关信息。有点类似于FILE
接着是dirent结构体,首先我们要弄清楚目录文件(directory file)的概念:这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针(摘自《UNIX环境高级编程(第二版)》)。从定义能够看出,dirent不仅仅指向目录,还指向目录中的具体文件,readdir函数同样也读取目录下的文件
同样先对目录信息进行一个了解
目录信息结构体如下所示:
struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* not an offset; see NOTES */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all filesystem types */ char d_name[256]; /* filename */ };
索引节点
和文件信息结构体一样,目录结构体也是有索引节点号的
在目录文件中的偏移
文件名长
文件类型
enum { DT_UNKNOWN = 0, //未知类型 # define DT_UNKNOWN DT_UNKNOWN DT_FIFO = 1, //管道 # define DT_FIFO DT_FIFO DT_CHR = 2, //字符设备 # define DT_CHR DT_CHR DT_DIR = 4, //目录 # define DT_DIR DT_DIR DT_BLK = 6, //块设备 # define DT_BLK DT_BLK DT_REG = 8, //常规文件 # define DT_REG DT_REG DT_LNK = 10, //符号链接 # define DT_LNK DT_LNK DT_SOCK = 12, //套接字 # define DT_SOCK DT_SOCK DT_WHT = 14 //链接 # define DT_WHT DT_WHT };
文件名,最长255字符
#include<sys/types.h> #include<dirent.h>
DIR *opendir(const char *name); DIR *fdopendir(int fd);
打开一个目录
#include <dirent.h>
struct dirent *readdir(DIR *dirp); int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); Feature Test Macro Requirements for glibc (see feature_test_macros(7)): readdir_r(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE
读取目录
//用来将当前的工作目录改变成以参数fd 所指的文件描述词。 int fchdir(int fd); //用来设置参数dir 目录流目前的读取位置为原来开头的读取位置. void rewinddir(DIR *dp); //关闭参数dir所指的目录流。关闭成功则返回0,失败返回-1,错误原因存于errno 中。 int closedir(DIR *dp); //作用是用于记录着一个目录流的位置。 long telldir(DIR *dp); //用来设置参数dir目录流读取位置,在调用readdir()时便从此新位置开始读取。参数offset 代表距离目录文件开头的偏移量。错误代码 EBADF 参数dir为无效的目录流。 void seekdir(DIR *dp,long loc);
#include <dirent> #include<sys/types.h> int main(int argc, char* argv[]) { DIR * dp = opendir("\test"); //打开目录,将信息存至DIR结构体中 if(dp == NULL) //检查 { perror("open dir fail..."); return 0; } struct dirent * p_dirent; //定义dirent结构体 while((p_dirent = readdir(dp)) != NULL) //遍历文件夹下所有的子文件,将其文件信息存至dirent结构体中 { if((strcmp(p_dirent ->d_name, ".") == 0) || (strcmp(p_dirent ->d_name, "."))) //过滤"."和".."文件夹,当寻找到"."和".."时,跳出当前循环 { continue; } } return 0; }