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

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

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

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

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

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

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

函数原型与结构体

opendir原型:

DIR *opendir(const char *path);

返回值:NULL  打开目录失败
readdir原型:

struct dirent *dir_entry;    //存储获取的目录内容

struct dirent *readdir(DIR *dirp);

返回值:NULL说明获取目录内容失败或者目录内容已经全部读取完成 ;
closedir原型:

int closedir(DIR *dirp);

返回值:0正常 -1错误

需要头文件<sys/stat.h>,<dirent.h>

dirent结构体内容:

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

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

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

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

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

DIR 结构体内容:

struct __dirstream
{
void *__fd; /* `struct hurd_fd' pointer for descriptor.   */
char *__data; /* Directory block.   */
int __entry_data; /* Entry number `__data' corresponds to.   */
char *__ptr; /* Current pointer into the block.   */
int __entry_ptr; /* Entry number `__ptr' corresponds to.   */
size_t __allocation; /* Space allocated for the block.   */
size_t __size; /* Total valid data in the block.   */
__libc_lock_define (, __lock) /* Mutex lock for this structure.   */
};
typedef struct __dirstream DIR;

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

例程

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

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/types.h>

void getDir(){
    //传入一个有效路径
    std::string path = "/Users/fileTest";
    struct stat sb;
    //判断该路径是否是目录
    if(stat(path.c_str(),&sb)!=0||!S_ISDIR(sb.st_mode)){
        return;
    }
    struct dirent* ent = nullptr;
    DIR *pDir = nullptr;
    pDir = opendir(path.c_str());
    while (nullptr != (ent=readdir(pDir))) {
        //文件夹里默认存在.和..,直接跳过
        if(strcmp(ent->d_name,".")==0||strcmp(ent->d_name,"..")==0) continue;
        //如果是一个文件夹
        if (ent->d_reclen == 32) {
            std::cout<<"folder:"<<ent->d_name<<std::endl;
        }else{//如果是一个文件
            std::cout<<"file:"<<ent->d_name<<std::endl;
        }
    }
    closedir(pDir);
}

int main(int argc, const char * argv[]) {
    // insert code here...
    getDir();
    return 0;
}

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

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

猜你喜欢

转载自blog.csdn.net/m0_37872216/article/details/126972644
今日推荐