Linux下C++遍历文件夹

图片来源:https://www.pixiv.net/en/artworks/101379672

使用POSIX函数

#include <ftw.h>

int nftw(const char *dirpath,
        int (*fn)(const char *fpath, const struct stat *sb,
                    int typeflag, struct FTW *ftwbuf),
        int nopenfd, int flags);

其中

  • dirpath:要遍历的文件夹路径
  • fn:回调函数,会为每个文件调用该函数,其中
    • fpath文件路径
    • sb:包含fpath文件信息的stat结构
    • typeflag:文件类型,值为FTW_D表示fpath是目录
    • ftwbuf:结构包含两个整数baselevel
      • ftwbuf->base:文件名偏移,使用fpath[ftwbuf->base]可以获取不包含路径的文件名
      • ftwbuf->level:当前深度
  • nopenfd:最大打开文件描述符数量,该值过大可能会导致运行缓慢(即使该值小于文件树深度也不影响遍历)
  • flags:遍历时的选项,默认不修改则使用0,下列选项可任意组合(使用“|”)
    • FTW_PHYS:不遍历软连接的文件夹(默认会遍历)
    • FTW_MOUNT:不会越界进入另一个文件系统
    • FTW_CHDIR:处理目录内容之前先调用 chdir()进入每个目录
    • FTW_DEPTH:先遍历文件树顶层目录(默认为先遍历子目录)
#include <iostream>
#include <ftw.h>
#include <unistd.h>

void recursive_dir(const char *path_name)
{
    nftw(
        path_name,
        [](const char *fpath, const struct stat *sb,
           int typeflag, struct FTW *ftwbuf) -> int
        {
            if (typeflag == FTW_D)
                std::cout << std::endl
                          << fpath << ':' << std::endl;
            else
                std::cout << fpath << std::endl;
            return 0;
        },
        16,
        0   /*使用默认遍历选项,默认会遍历软连接的目录*/
    );
}

int main(int, char **)
{
    // 遍历当前文件夹及其子文件夹
    // get_current_dir_name()是GNU扩展,POSIX里功能类似的函数是getcwd()
    recursive_dir(get_current_dir_name());
}

使用C++ 17新增的filesystem库

#include <iostream>
#include <filesystem>

namespace fs = std::filesystem;

void recursive_dir(fs::path path_name)
{
    //递归遍历文件夹,遇到软连接的文件夹也会遍历
    for (auto const &dir_ent : fs::recursive_directory_iterator(path_name,
                                fs::directory_options::follow_directory_symlink))
    {
        if (dir_ent.is_directory())
            std::cout << std::endl
                      << dir_ent << ':' << std::endl;
        else
            std::cout << dir_ent << std::endl;
    }
}

int main(int, char **)
{
    // 遍历当前文件夹及其子文件夹
    recursive_dir(fs::current_path());
}

参考:

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注