![](/img/trans.png)
[英]How to implement recursive directories and files listing using std::filesystem?
[英]Recursive function for listing all files in sub directories
我正在嘗試編寫一個函數,該函數返回當前文件夾及其所有子文件夾中所有文件的列表。 我寫了這段代碼:
#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;
}
我在谷歌搜索它,但我不知道如何:
pdir
是否為目錄同時我把所有東西都放在 main 上,因為我仍然不知道遞歸函數應該有什么參數。
有什么提示嗎?
這是一個使用建議的標准文件系統庫的版本:
#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";
}
除非您的目標是學習如何編寫遞歸函數,否則您可能更喜歡這個基於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
}
}
甚至是單個函數調用:
std::copy(
boost::filesystem::recursive_directory_iterator("./"),
boost::filesystem::recursive_directory_iterator(),
std::ostream_iterator<boost::filesystem::directory_entry>(std::cout, "\n"));
我在 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);
}
}
用法:
listFiles("my_directory/", [](const std::string &path) {
std::cout << path << std::endl;
});
將該代碼隔離在一個將基本目錄路徑作為參數的過程中,這樣您就可以實際執行遞歸調用。 應該是這樣的
void recursive_file_list(const char * directory)
{
// ...
}
然后,檢查你得到的pdir
是否是一個目錄,你有兩條路線:
pdir->d_type==DT_DIR
; 這會立即為您提供此信息,但它不可移植(POSIX 不d_type
成員的存在); 此外,並非所有文件系統都支持它,因此您可能會得到DT_UNKNOWN
。 如果你想跟隨符號鏈接,如果你得到DT_LNK
,你還必須執行額外的檢查。 在這些情況下,您必須回退到lstat
(請參閱下面的要點);lstat
來獲取有關每個文件的信息,特別是檢查struct stat
的st_mode
字段。使用 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';
}
}
}
使用示例輸出:
"/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"
它使用標准的 c++ 功能。 無需在代碼中包含任何第三方庫。
僅將目錄路徑作為參數發送。 它將還原該文件夾及其子文件夾中存在的每個文件路徑。
此外,如果您需要對任何特定類型的文件(即 .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;
}
路徑應該類似於/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);
}
您可以檢查是否沒有“。” 在字符串中。
if(strstr(pdir->d_name,".") != NULL)
這是我如何使用它
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;
}
很棒的東西,這是我僅使用 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.