[英]Recursive function for listing all files in sub directories
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:我在谷歌搜索它,但我不知道如何:
pdir
is directorypdir
是否为目录Meanwhile I have everything on main because I still don't know what arguments the recursive function should have.同时我把所有东西都放在 main 上,因为我仍然不知道递归函数应该有什么参数。
Any hints?有什么提示吗?
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";
}
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"));
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;
});
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
是否是一个目录,你有两条路线:
pdir->d_type==DT_DIR
;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_type
member);d_type
成员的存在); also, it's not supported for all the filesystems, so you may get DT_UNKNOWN
.DT_UNKNOWN
。 If you want to follow symlinks, you have to perform extra checks also if you get DT_LNK
.DT_LNK
,你还必须执行额外的检查。 In these cases, you must fall back to lstat
(see the point below);lstat
(请参阅下面的要点);lstat
to get information about each file, checking in particular the st_mode
field of struct stat
.lstat
来获取有关每个文件的信息,特别是检查struct stat
的st_mode
字段。Using C++17 recursive_directory_iterator it 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"
It uses standard c++ functionality.它使用标准的 c++ 功能。 No need to include any third party library in code.
无需在代码中包含任何第三方库。
Only send directory path as parameter.仅将目录路径作为参数发送。 It will revert you every files path present in that folder and its sub folder.
它将还原该文件夹及其子文件夹中存在的每个文件路径。
Further that, if you need to sort any specific type file (ie .txt or.jpg), pass extension, it will print all the files path which having respective extension.此外,如果您需要对任何特定类型的文件(即 .txt 或 .jpg)进行排序,传递扩展名,它将打印具有相应扩展名的所有文件路径。
#include <Windows.h>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
vector<string> files;
std::string Recursive(std::string folder) {
std::string search_path = folder + "/*.*";
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
std::string tmp;
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (!(!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, ".."))) {
tmp = folder + "\\";
tmp = tmp + fd.cFileName;
Recursive(tmp);
}
}
else {
std::string FinalFilePath = folder + "\\" + fd.cFileName;
files.push_back(FinalFilePath);
}
} while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return folder;
}
bool has_suffix(const std::string& str, const std::string& suffix) {
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
int main(){
std::string folder = "C:\\Users\\Omkar\\Desktop\\Test";
Recursive(folder);
std::string t;
const auto needle = std::string(".txt");
while (!files.empty()) {
t = files.back();
if (has_suffix(t, ".mmt")) {
cout << "FINAL PATH : " << t << endl;
t.clear();
}
files.pop_back();
}
return 0;
}
Path should look like /your_path/
.路径应该类似于
/your_path/
。 For search inside hidden folders you should add third parameter true
.要在隐藏文件夹中搜索,您应该添加第三个参数
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);
}
You could check if there is no "."您可以检查是否没有“。” in the string.
在字符串中。
if(strstr(pdir->d_name,".") != NULL)
Here how I use it这是我如何使用它
std::vector<std::string> get_all_files_recursive(const fs::path& path)
{
std::vector<std::string> result;
for (const auto& p : fs::recursive_directory_iterator(path))
{
if (!fs::is_directory(p))
{
fs::path path = p.path();
result.push_back(path.u8string());
}
}
return result;
}
Great stuff, Here is my Windows friendly solution using std only since i had few bumps with the above solutions on Windows specifically: works in DLLs as well:很棒的东西,这是我仅使用 std 的 Windows 友好解决方案,因为我在 Windows 上对上述解决方案没有什么特别的意见:也适用于 DLL:
#include <windows.h> // messagebox
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
#include <filesystem> // C++17 standard header file name
#include <experimental/filesystem> // Header file for pre-standard implementation
using namespace std::experimental::filesystem::v1;
for (recursive_directory_iterator next(path(dir.c_str())), end; next != end; ++next)
{
auto path = next->path();
if (path.has_extension())
{
MessageBox(0, path.wstring().c_str(), L"Filepath", 0);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.