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

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


当前回答

基于上面的答案

#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

其他回答

GNU手册FTW

http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister

此外,有时直接找到源头是件好事(双关)。通过查看Linux中一些最常见命令的内部结构,您可以学到很多东西。我在github上建立了一个GNU coreutils的简单镜像(供阅读)。

https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c

也许这并不能解决Windows的问题,但是通过使用这些方法,可以实现使用Unix变体的许多情况。

希望这对你有所帮助……

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也可以遍历子目录。

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

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;
}

尝试x平台方法

http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm

或者只是使用特定于操作系统的文件。

由于目录下的文件和子目录一般存储在树状结构中,一种直观的方法是使用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);
}