Как я могу получить список файлов в каталоге, используя C или C ++? - PullRequest
521 голосов
/ 04 марта 2009

Как определить список файлов в каталоге из моего кода C или C ++?

Мне не разрешено выполнять команду ls и анализировать результаты из моей программы.

Ответы [ 24 ]

1 голос
/ 03 июля 2014

Системный вызов!

system( "dir /b /s /a-d * > file_names.txt" );

Тогда просто прочитайте файл.

РЕДАКТИРОВАТЬ: Этот ответ следует считать хаком, но он действительно работает (хотя и в зависимости от платформы), если у вас нет доступа к более элегантным решениям.

0 голосов
/ 29 сентября 2018

Просто то, чем я хочу поделиться и поблагодарить вас за материал для чтения. Поиграйте с функцией, чтобы немного ее понять. Вам может понравиться это. e обозначает расширение, p обозначает путь, а s обозначает разделитель пути.

Если путь пройден без конечного разделителя, разделитель будет добавлен к пути. Для расширения, если введена пустая строка, функция вернет любой файл, который не имеет расширения в своем имени. Если была введена одна звезда, будут возвращены все файлы в каталоге. Если длина e больше 0, но не является единичным *, то точка e будет добавлена ​​к e, если 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;
}
0 голосов
/ 25 сентября 2018

Я пытался следовать примеру, приведенному в оба ответы , и, возможно, стоит отметить, что похоже, что 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 << привела к отсутствующей ошибке перегрузки.

0 голосов
/ 28 июня 2017

Это сработало для меня. Он пишет файл только с именами (без пути) всех файлов. Затем он читает этот текстовый файл и печатает его для вас.

void DisplayFolderContent()
    {

        system("dir /n /b * > file_names.txt");
        char ch;
        std::fstream myStream("file_names.txt", std::fstream::in);
        while (myStream.get(ch))
        {
            std::cout << ch;
        }

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...