• Linux 文件/目录访问(opendir/closedir/readdir)


    在Linux系统中我们需要在一个特定目录下对该目录下所有的文件以及目录(文件夹)进行便利访问。

    Linux获取目录文件的流程如下:

    1.打开指定目录,使用opendir得到目录句柄。

    2.while循环中使用readdir获取目录的内容,并存储到struct dirent 结构体变量中。

    3.dirent结构体变量存储了文件/文件夹的一些属性,可以通过这些属性进行一些差异化操作。

    4.最后关闭目录句柄closedir。

    函数原型与结构体

    1. opendir原型:
    2. DIR *opendir(const char *path);
    3. 返回值:NULL 打开目录失败
    1. readdir原型:
    2. struct dirent *dir_entry; //存储获取的目录内容
    3. struct dirent *readdir(DIR *dirp);
    4. 返回值:NULL说明获取目录内容失败或者目录内容已经全部读取完成 ;
    1. closedir原型:
    2. int closedir(DIR *dirp);
    3. 返回值:0正常 -1错误

    需要头文件

    1. dirent结构体内容:
    2. struct dirent
    3. {
    4. long d_ino; /* inode number 索引节点号 */
    5. off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
    6. unsigned short d_reclen; /* length of this d_name 文件名长 */
    7. unsigned char d_type; /* the type of d_name 文件类型 */
    8. char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
    9. }

    dirent结构体常用的三个变量是d_reclen,d_type,d_name。

    d_reclen 表示的是文件名长度,6表示子目录或以.开头的隐藏文件,24表示普通文本文件,28为二进制文件,32表示文件夹。

    d_type 表示的是当前的类型,该值为4说明这是一个文件夹,该值为8说明这是一个文件。

    d_name 表示的是当前文件/文件夹的名称。

     

    1. DIR 结构体内容:
    2. struct __dirstream
    3. {
    4. void *__fd; /* `struct hurd_fd' pointer for descriptor. */
    5. char *__data; /* Directory block. */
    6. int __entry_data; /* Entry number `__data' corresponds to. */
    7. char *__ptr; /* Current pointer into the block. */
    8. int __entry_ptr; /* Entry number `__ptr' corresponds to. */
    9. size_t __allocation; /* Space allocated for the block. */
    10. size_t __size; /* Total valid data in the block. */
    11. __libc_lock_define (, __lock) /* Mutex lock for this structure. */
    12. };
    13. typedef struct __dirstream DIR;

    DIR结构体的内容不太需要关注。 

    例程

    给定一个路径,去遍历路径下的有效文件:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. void getDir(){
    10. //传入一个有效路径
    11. std::string path = "/Users/fileTest";
    12. struct stat sb;
    13. //判断该路径是否是目录
    14. if(stat(path.c_str(),&sb)!=0||!S_ISDIR(sb.st_mode)){
    15. return;
    16. }
    17. struct dirent* ent = nullptr;
    18. DIR *pDir = nullptr;
    19. pDir = opendir(path.c_str());
    20. while (nullptr != (ent=readdir(pDir))) {
    21. //文件夹里默认存在.和..,直接跳过
    22. if(strcmp(ent->d_name,".")==0||strcmp(ent->d_name,"..")==0) continue;
    23. //如果是一个文件夹
    24. if (ent->d_reclen == 32) {
    25. std::cout<<"folder:"<d_name<
    26. }else{//如果是一个文件
    27. std::cout<<"file:"<d_name<
    28. }
    29. }
    30. closedir(pDir);
    31. }
    32. int main(int argc, const char * argv[]) {
    33. // insert code here...
    34. getDir();
    35. return 0;
    36. }

    需要注意的一个点是,.和..是在Unix 以及所有类unix系统中,在文件夹中默认生成的,.表示当前文件夹,..表示当前文件夹的父文件夹。通常我们是不需要两个隐藏文件夹的,因此在遍历的时候直接跳过了。

    此外,传入一个路径的时候我们需要判断该路径是否是一个合法目录,因此需要额外判断。

  • 相关阅读:
    Oracle 创建表语句
    搭建云原生环境
    Kepware带你玩转IEC60870-104驱动
    C# 修改打印机名称
    100天精通Python(数据分析篇)——第53天:初始pandas模块
    spark安装与入门
    MongoDB副本集调整节点
    Linux环境更换阿里源(CentOS+Ubuntu)
    shiro-第一篇-基本介绍及使用
    【分享】golang windows 运行报错 undefined: syscall.SIGUSR1
  • 原文地址:https://blog.csdn.net/m0_37872216/article/details/126972644