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
Recursive function for listing all files in sub directories
提问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
pdir
is 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 pdir
you 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 thed_type
member); also, it's not supported for all the filesystems, so you may getDT_UNKNOWN
. If you want to follow symlinks, you have to perform extra checks also if you getDT_LNK
. In these cases, you must fall back tolstat
(see the point below); - you can instead portably use
lstat
to get information about each file, checking in particular thest_mode
field ofstruct 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)