如何从我的C或c++代码中确定目录中的文件列表?
我不允许在程序中执行ls命令并解析结果。
如何从我的C或c++代码中确定目录中的文件列表?
我不允许在程序中执行ls命令并解析结果。
当前回答
Shreevardhan的设计也适用于遍历子目录:
#include <string>
#include <iostream>
#include <filesystem>
using namespace std;
namespace fs = filesystem;
int main()
{
string path = "\\path\\to\\directory";
// string path = "/path/to/directory";
for (auto & p : fs::recursive_directory_iterator(path))
cout << p.path() << endl;
}
编译:cl /EHsc /W4 /WX /std:c++17 ListFiles.cpp
其他回答
基于上面的答案
#include <vector>
#include <string>
#include <algorithm>
#ifdef _WIN32
#include <windows.h>
std::vector<std::string> files_in_directory(std::string path)
{
std::vector<std::string> files;
// check directory exists
char fullpath[MAX_PATH];
GetFullPathName(path.c_str(), MAX_PATH, fullpath, 0);
std::string fp(fullpath);
if (GetFileAttributes(fp.c_str()) != FILE_ATTRIBUTE_DIRECTORY)
return files;
// get file names
WIN32_FIND_DATA findfiledata;
HANDLE hFind = FindFirstFile((LPCSTR)(fp + "\\*").c_str(), &findfiledata);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
files.push_back(findfiledata.cFileName);
}
while (FindNextFile(hFind, &findfiledata));
FindClose(hFind);
}
// delete current and parent directories
files.erase(std::find(files.begin(), files.end(), "."));
files.erase(std::find(files.begin(), files.end(), ".."));
// sort in alphabetical order
std::sort(files.begin(), files.end());
return files;
}
#else
#include <dirent.h>
std::vector<std::string> files_in_directory(std::string directory)
{
std::vector<std::string> files;
// open directory
DIR *dir;
dir = opendir(directory.c_str());
if (dir == NULL)
return files;
// get file names
struct dirent *ent;
while ((ent = readdir(dir)) != NULL)
files.push_back(ent->d_name);
closedir(dir);
// delete current and parent directories
files.erase(std::find(files.begin(), files.end(), "."));
files.erase(std::find(files.begin(), files.end(), ".."));
// sort in alphabetical order
std::sort(files.begin(), files.end());
return files;
}
#endif // _WIN32
我希望这段代码对您有所帮助。
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string wchar_t2string(const wchar_t *wchar)
{
string str = "";
int index = 0;
while(wchar[index] != 0)
{
str += (char)wchar[index];
++index;
}
return str;
}
wchar_t *string2wchar_t(const string &str)
{
wchar_t wchar[260];
int index = 0;
while(index < str.size())
{
wchar[index] = (wchar_t)str[index];
++index;
}
wchar[index] = 0;
return wchar;
}
vector<string> listFilesInDirectory(string directoryName)
{
WIN32_FIND_DATA FindFileData;
wchar_t * FileName = string2wchar_t(directoryName);
HANDLE hFind = FindFirstFile(FileName, &FindFileData);
vector<string> listFileNames;
listFileNames.push_back(wchar_t2string(FindFileData.cFileName));
while (FindNextFile(hFind, &FindFileData))
listFileNames.push_back(wchar_t2string(FindFileData.cFileName));
return listFileNames;
}
void main()
{
vector<string> listFiles;
listFiles = listFilesInDirectory("C:\\*.txt");
for each (string str in listFiles)
cout << str << endl;
}
c++ 17现在有了std::filesystem::directory_iterator,它可以用作
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
std::string path = "/path/to/directory";
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
}
另外,std::filesystem::recursive_directory_iterator也可以遍历子目录。
这是我想分享的一些东西,谢谢你们的阅读材料。稍微摆弄一下这个函数来理解它。你可能会喜欢的。E表示扩展,p表示路径,s表示路径分隔符。
如果传递路径时没有结束分隔符,则将在路径后附加分隔符。对于扩展名,如果输入的是空字符串,则函数将返回名称中没有扩展名的任何文件。如果只输入一个星号,则将返回目录中的所有文件。如果e的长度大于0,但不是一个*,那么如果e在0点位置没有包含一个点,则会在e前面加上一个点。
对于返回值。如果返回一个零长度的映射,则什么也没有找到,但是目录是打开的。如果返回值中索引999是可用的,但映射大小只有1,那么这意味着打开目录路径有问题。
注意,为了提高效率,这个函数可以分成3个更小的函数。在此基础上,您可以创建一个调用方函数,该函数将根据输入检测将要调用的函数。为什么这样更有效率?也就是说,如果你要抓取所有属于文件的东西,执行那个方法这个为抓取所有文件而构建的子函数只会抓取所有属于文件的东西而不需要在每次找到一个文件时评估任何其他不必要的条件。
这也适用于抓取没有扩展名的文件。为此目的构建的特定函数只在找到的对象是一个文件时计算天气,然后计算文件名称中是否有点。
如果只读取文件不多的目录,节省的时间可能不多。但是,如果您正在读取大量的目录,或者如果目录有数十万个文件,这可能是一个巨大的节省。
#include <stdio.h>
#include <sys/stat.h>
#include <iostream>
#include <dirent.h>
#include <map>
std::map<int, std::string> getFile(std::string p, std::string e = "", unsigned char s = '/'){
if ( p.size() > 0 ){
if (p.back() != s) p += s;
}
if ( e.size() > 0 ){
if ( e.at(0) != '.' && !(e.size() == 1 && e.at(0) == '*') ) e = "." + e;
}
DIR *dir;
struct dirent *ent;
struct stat sb;
std::map<int, std::string> r = {{999, "FAILED"}};
std::string temp;
int f = 0;
bool fd;
if ( (dir = opendir(p.c_str())) != NULL ){
r.erase (999);
while ((ent = readdir (dir)) != NULL){
temp = ent->d_name;
fd = temp.find(".") != std::string::npos? true : false;
temp = p + temp;
if (stat(temp.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)){
if ( e.size() == 1 && e.at(0) == '*' ){
r[f] = temp;
f++;
} else {
if (e.size() == 0){
if ( fd == false ){
r[f] = temp;
f++;
}
continue;
}
if (e.size() > temp.size()) continue;
if ( temp.substr(temp.size() - e.size()) == e ){
r[f] = temp;
f++;
}
}
}
}
closedir(dir);
return r;
} else {
return r;
}
}
void printMap(auto &m){
for (const auto &p : m) {
std::cout << "m[" << p.first << "] = " << p.second << std::endl;
}
}
int main(){
std::map<int, std::string> k = getFile("./", "");
printMap(k);
return 0;
}
由于目录下的文件和子目录一般存储在树状结构中,一种直观的方法是使用DFS算法递归遍历每个目录。 下面是一个在windows操作系统中使用io.h中的基本文件函数的例子。您可以在其他平台上替换这些功能。我想表达的是,DFS的基本思想完美地满足了这个问题。
#include<io.h>
#include<iostream.h>
#include<string>
using namespace std;
void TraverseFilesUsingDFS(const string& folder_path){
_finddata_t file_info;
string any_file_pattern = folder_path + "\\*";
intptr_t handle = _findfirst(any_file_pattern.c_str(),&file_info);
//If folder_path exsist, using any_file_pattern will find at least two files "." and "..",
//of which "." means current dir and ".." means parent dir
if (handle == -1){
cerr << "folder path not exist: " << folder_path << endl;
exit(-1);
}
//iteratively check each file or sub_directory in current folder
do{
string file_name=file_info.name; //from char array to string
//check whtether it is a sub direcotry or a file
if (file_info.attrib & _A_SUBDIR){
if (file_name != "." && file_name != ".."){
string sub_folder_path = folder_path + "\\" + file_name;
TraverseFilesUsingDFS(sub_folder_path);
cout << "a sub_folder path: " << sub_folder_path << endl;
}
}
else
cout << "file name: " << file_name << endl;
} while (_findnext(handle, &file_info) == 0);
//
_findclose(handle);
}