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

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


当前回答

对于C的唯一解决方案,请检查这个。它只需要一个额外的头文件:

https://github.com/cxong/tinydir

tinydir_dir dir;
tinydir_open(&dir, "/path/to/dir");

while (dir.has_next)
{
    tinydir_file file;
    tinydir_readfile(&dir, &file);

    printf("%s", file.name);
    if (file.is_dir)
    {
        printf("/");
    }
    printf("\n");

    tinydir_next(&dir);
}

tinydir_close(&dir);

与其他选项相比,以下是一些优势:

它是可移植的-包装POSIX的dirent和Windows的FindFirstFile 它在可用的地方使用readdir_r,这意味着它(通常)是线程安全的 通过相同的UNICODE宏支持Windows UTF-16 它是C90,所以即使是非常古老的编译器也可以使用它

其他回答

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变体的许多情况。

希望这对你有所帮助……

为什么不使用glob()?

#include <glob.h>

glob_t glob_result;
glob("/your_directory/*",GLOB_TILDE,NULL,&glob_result);
for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
  cout << glob_result.gl_pathv[i] << endl;
}
#include<iostream>
#include <dirent.h>
using namespace std;
char ROOT[]={'.'};

void listfiles(char* path){
    DIR * dirp = opendir(path);
    dirent * dp;
    while ( (dp = readdir(dirp)) !=NULL ) {
         cout << dp->d_name << " size " << dp->d_reclen<<std::endl;
    }
    (void)closedir(dirp);
}

int main(int argc, char **argv)
{
    char* path;
    if (argc>1) path=argv[1]; else path=ROOT;

    cout<<"list files in ["<<path<<"]"<<std::endl;
    listfiles(path);

    return 0;
}

我试图遵循两个回答中给出的示例,可能值得注意的是,似乎std::filesystem::directory_entry已被更改为不重载<<操作符。而不是std::cout << p << std::endl;我必须使用以下能够编译并让它工作:

#include <iostream>
#include <filesystem>
#include <string>
namespace fs = std::filesystem;

int main() {
    std::string path = "/path/to/directory";
    for(const auto& p : fs::directory_iterator(path))
        std::cout << p.path() << std::endl;
}

试图将p单独传递给std::cout <<会导致丢失重载错误。

我建议在这个可重用的包装器中使用glob。它生成一个vector<string>,对应于符合glob模式的文件路径:

#include <glob.h>
#include <vector>
using std::vector;

vector<string> globVector(const string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    vector<string> files;
    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
        files.push_back(string(glob_result.gl_pathv[i]));
    }
    globfree(&glob_result);
    return files;
}

然后可以使用普通的系统通配符模式调用,例如:

vector<string> files = globVector("./*");