C++ 列出子目录中所有文件的递归函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13129340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:00:12  来源:igfitidea点击:

Recursive function for listing all files in sub directories

c++

提问by Maroun

I'm trying to write a function that returns a list of all files on current folder and all of its sub folders. I wrote this code:

我正在尝试编写一个函数,该函数返回当前文件夹及其所有子文件夹中所有文件的列表。我写了这段代码:

#include <iostream>
#include <dirent.h>
#include <cstring>

using namespace std;

int main() {
   DIR* dir; dirent* pdir;
   //From my workspace
   dir=opendir(".");     
   while (pdir=readdir(dir)) {
       if(/**********This pdir is a directory**********/) {
           /**********RECURSIVE CALL SHOULD BE HERE**********/
           cout<<pdir->d_name<<endl;
       }
   }
   closedir(dir);
   return 0;
}

I searched for it in google and I don't know how to:

我在谷歌搜索它,我不知道如何:

  • Check if the current pdiris directory
  • Go inside the directory and perform the recursive call on it
  • 检查当前pdir是否为目录
  • 进入目录并对其执行递归调用

Meanwhile I have everything on main because I still don't know what arguments the recursive function should have.

同时我把所有东西都放在 main 上,因为我仍然不知道递归函数应该有什么参数。

Any hints?

任何提示?

采纳答案by Matteo Italia

Isolate that code in a procedure that takes the base directory path as a parameter, so you can actually perform the recursive call. It should be something like

在将基本目录路径作为参数的过程中隔离该代码,以便您可以实际执行递归调用。它应该是这样的

void recursive_file_list(const char * directory)
{
    // ...
}

Then, to check if the pdiryou obtained is a directory, you have two routes:

然后,要检查pdir您获得的是否是目录,您有两条路线:

  • you can check if pdir->d_type==DT_DIR; this gives you this information immediately, but it's not portable (POSIX does not mandate the existence of the d_typemember); also, it's not supported for all the filesystems, so you may get DT_UNKNOWN. If you want to follow symlinks, you have to perform extra checks also if you get DT_LNK. In these cases, you must fall back to lstat(see the point below);
  • you can instead portably use lstatto get information about each file, checking in particular the st_modefield of struct stat.
  • 你可以检查是否pdir->d_type==DT_DIR; 这会立即为您提供此信息,但它不可移植(POSIX 不强制要求d_type成员存在);此外,并非所有文件系统都支持它,因此您可能会得到DT_UNKNOWN. 如果你想跟随符号链接,你必须执行额外的检查,如果你得到DT_LNK. 在这些情况下,您必须退回到lstat(请参阅以下要点);
  • 您可以改为移植应用lstat,以获取有关每个文件的信息,特别是检查st_mode的领域struct stat

回答by Paul Jurczak

Here is a version using proposed standard filesystem library:

这是使用建议的标准文件系统库的版本:

#include <iostream>
#include <filesystem>

using namespace std;
using namespace std::tr2::sys;

void main()
{   
  for (recursive_directory_iterator i("."), end; i != end; ++i) 
    if (!is_directory(i->path()))
      cout << i->path().filename() << "\n";
} 

回答by Rob?

Unless your goal is to learn how to write a recursive function, you might prefer this simple loop based on Boost.Filesystem:

除非您的目标是学习如何编写递归函数,否则您可能更喜欢这个基于Boost.Filesystem 的简单循环:

#include "boost/filesystem.hpp"
#include <iostream>

int main () {
  for ( boost::filesystem::recursive_directory_iterator end, dir("./");
    dir != end; ++dir ) {
    // std::cout << *dir << "\n";  // full path
    std::cout << dir->path().filename() << "\n"; // just last bit
  }
}

Or even the single function call:

甚至是单个函数调用:

std::copy(
  boost::filesystem::recursive_directory_iterator("./"),
  boost::filesystem::recursive_directory_iterator(),
  std::ostream_iterator<boost::filesystem::directory_entry>(std::cout, "\n"));

回答by AdrianEddy

My approach in C++11:

我在 C++11 中的方法:

#include <string>
#include <functional>
#include <dirent.h>

void listFiles(const std::string &path, std::function<void(const std::string &)> cb) {
    if (auto dir = opendir(path.c_str())) {
        while (auto f = readdir(dir)) {
            if (!f->d_name || f->d_name[0] == '.') continue;
            if (f->d_type == DT_DIR) 
                listFiles(path + f->d_name + "/", cb);

            if (f->d_type == DT_REG)
                cb(path + f->d_name);
        }
        closedir(dir);
    }
}

Usage:

用法:

listFiles("my_directory/", [](const std::string &path) {
    std::cout << path << std::endl;
});

回答by Le?ny Rumcajs

Using C++17 recursive_directory_iteratorit becomes as concise as:

使用 C++17 recursive_directory_iterator它变得如此简洁:

void ls_recursive(const std::filesystem::path& path) {
    for(const auto& p: std::filesystem::recursive_directory_iterator(path)) {
        if (!std::filesystem::is_directory(p)) {
            std::cout << p.path() << '\n';
        }
    }
}

With example output:

使用示例输出:

"/home/user/prj/rust/stack/Cargo.toml"
"/home/user/prj/rust/stack/.gitignore"
"/home/user/prj/rust/stack/src/main.rs"
"/home/user/prj/rust/stack/.git/config"

回答by Victor

Path should look like /your_path/. For search inside hidden folders you should add third parameter true.

路径应该看起来像 /your_path/. 要在隐藏文件夹中搜索,您应该添加第三个参数true

#include <dirent.h>
#include <vector>
#include <cstring>    

void GetReqDirs(const std::string& path, std::vector<string>& files,const bool showHiddenDirs = false){
    DIR *dpdf;
    struct dirent *epdf;
    dpdf = opendir(path.c_str());
    if (dpdf != NULL){
        while ((epdf = readdir(dpdf)) != NULL){
            if(showHiddenDirs ? (epdf->d_type==DT_DIR && string(epdf->d_name) != ".." && string(epdf->d_name) != "." ) : (epdf->d_type==DT_DIR && strstr(epdf->d_name,"..") == NULL && strstr(epdf->d_name,".") == NULL ) ){
                GetReqDirs(path+epdf->d_name+"/",files, showHiddenDirs);
            }
            if(epdf->d_type==DT_REG){
                files.push_back(path+epdf->d_name);
            }
        }
    }
    closedir(dpdf);
}

回答by user1594121

You could check if there is no "." in the string.

您可以检查是否没有“。” 在字符串中。

if(strstr(pdir->d_name,".") != NULL)