如何从我的C或c++代码中确定目录中的文件列表?

我不允许在程序中执行ls命令并解析结果。


当前回答

看看这个使用win32 api的类。只需要构造一个实例,提供您想要清单的文件夹名,然后调用getNextFile方法从目录中获取下一个文件名。我认为它需要windows.h和stdio.h。

class FileGetter{
    WIN32_FIND_DATAA found; 
    HANDLE hfind;
    char folderstar[255];       
    int chk;

public:
    FileGetter(char* folder){       
        sprintf(folderstar,"%s\\*.*",folder);
        hfind = FindFirstFileA(folderstar,&found);
        //skip .
        FindNextFileA(hfind,&found);        
    }

    int getNextFile(char* fname){
        //skips .. when called for the first time
        chk=FindNextFileA(hfind,&found);
        if (chk)
            strcpy(fname, found.cFileName);     
        return chk;
    }

};

其他回答

这是我想分享的一些东西,谢谢你们的阅读材料。稍微摆弄一下这个函数来理解它。你可能会喜欢的。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;
}

下面是c++ 11中使用boost::filesystem库获取目录中的文件名(不包括文件夹名)的一个非常简单的代码:

#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;

int main()
{
    path p("D:/AnyFolder");
    for (auto i = directory_iterator(p); i != directory_iterator(); i++)
    {
        if (!is_directory(i->path())) //we eliminate directories
        {
            cout << i->path().filename().string() << endl;
        }
        else
            continue;
    }
}

输出如下:

file1.txt
file2.dat

这个实现实现了您的目的,用指定目录的内容动态填充字符串数组。

int exploreDirectory(const char *dirpath, char ***list, int *numItems) {
    struct dirent **direntList;
    int i;
    errno = 0;

    if ((*numItems = scandir(dirpath, &direntList, NULL, alphasort)) == -1)
        return errno;

    if (!((*list) = malloc(sizeof(char *) * (*numItems)))) {
        fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath);
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < *numItems; i++) {
        (*list)[i] = stringDuplication(direntList[i]->d_name);
    }

    for (i = 0; i < *numItems; i++) {
        free(direntList[i]);
    }

    free(direntList);

    return 0;
}

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

看看这个使用win32 api的类。只需要构造一个实例,提供您想要清单的文件夹名,然后调用getNextFile方法从目录中获取下一个文件名。我认为它需要windows.h和stdio.h。

class FileGetter{
    WIN32_FIND_DATAA found; 
    HANDLE hfind;
    char folderstar[255];       
    int chk;

public:
    FileGetter(char* folder){       
        sprintf(folderstar,"%s\\*.*",folder);
        hfind = FindFirstFileA(folderstar,&found);
        //skip .
        FindNextFileA(hfind,&found);        
    }

    int getNextFile(char* fname){
        //skips .. when called for the first time
        chk=FindNextFileA(hfind,&found);
        if (chk)
            strcpy(fname, found.cFileName);     
        return chk;
    }

};