3
votes

Lire tous les noms de fichiers dans un répertoire

J'essaye de lire tous les noms de fichiers présents dans un répertoire particulier. J'ai créé un programme en C ++ mais cela n'imprime que les fichiers directement dans ce répertoire. Je veux tous les fichiers qui sont également présents dans le sous-répertoire.

J'ai écrit un programme en c ++ qui imprime les noms de fichiers dans un répertoire mais je veux aussi tous les noms de fichiers dans le sous-répertoire.

#include <stdio.h>
#include <windows.h>
#include <bits/stdc++.h>
#include <dirent.h>
using namespace std;

#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <unistd.h>
#endif

#ifdef WIN32
#define stat _stat
#endif

int main ()
{
    DIR *dir;
    struct dirent *ent;
    if ((dir = opendir ("c:\\test")) != NULL) {
        /* print all the files and directories within directory */
        while ((ent = readdir (dir)) != NULL) {
            printf ("%s\n", ent->d_name);
        }
        closedir (dir);
    } else {
        /* could not open directory */
        perror ("");
        return EXIT_FAILURE;
    }
}


6 commentaires

Vous devez écrire une fonction récursive . C'est une tâche courante, je suis sûr que vous pouvez rechercher une réponse sur Google.


en.cppreference.com/w/cpp/experimental/fs/…


Par exemple, stackoverflow.com/questions/9138866/...


@john merci pour cela ... mais c'est pour Linux, je le veux pour Windows ...


J'ai du code pour la même exigence sur mon dépôt github. vous pouvez le vérifier ici github.com/mshingote/List-of-files-and-folders/blob/master/...


@ JohnWick1 La logique est identique sur Windows et Linux. L'API utilisée, opendir, readdir, closedir, etc. est également identique à votre code. Je suis sûr que vous pouvez traduire les différences mineures entre les deux plates-formes.


3 Réponses :


1
votes

Utilisation de C ++ 17 recursive_directory_iterator

#include <filesystem>

void ls_recursive(const std::filesystem::path& path) {
    for(const auto& p: std::filesystem::recursive_directory_iterator(path)) {
        std::cout << p.path() << '\n';
    }
}


3 commentaires

Hé merci mon cher ... Mais je suis nouveau dans la programmation, pouvez-vous me dire quoi passer en paramètre de fonction ..


Le chemin . Et si vous utilisez un compilateur plus ancien qui ne prend pas en charge C ++ 17, votre approche dirent est correcte.


Si votre compilateur ne prend pas en charge C ++ 17, vous pouvez toujours rechercher une solution similaire en utilisant boost - il est bon d'avoir du code multiplateforme à long terme et de ne pas vous attacher à WinAPI. En C ++ 14, recursive_directory_iterator serait dans experimental / filesystem .



2
votes

Si vous disposez de C ++ 17, utilisez recursive_directory_iterator . Sinon, vous pouvez utiliser les fonctions dirent.h . Prenons par exemple la fonction générique traverseFiles suivante, qui transmet chaque fichier trouvé à une fonction qui gère le fichier détecté:

#include <iostream>
#include <dirent.h>
#include <string>

void traverseFiles(const std::string &path, std::function<void(const std::string &)> cb) {
    if (auto dir = opendir(path.c_str())) {
        while (auto f = readdir(dir)) {
            if (f->d_name[0] == '.') continue;

            if (f->d_type == DT_DIR)
                traverseFiles(path + f->d_name + "/", cb);

            if (f->d_type == DT_REG)
                cb(path + f->d_name);
        }
        closedir(dir);
    }
}


void fileDetected(const std::string &f) {
    std::cout << "file:" << f << std::endl;
}


int main() {
    traverseFiles("c:/somestartdir", &fileDetected);
}


0 commentaires

0
votes

Si vous utilisez Windows OS, vous pouvez exécuter le code ci-dessous pour obtenir une liste de fichiers dans le répertoire fourni.

#include <windows.h>
#include <TCHAR.h>
#include <stdio.h>

void Enum(TCHAR root[0xFF])
{
    HANDLE hFind;
    WIN32_FIND_DATA wfd;
    TCHAR GeneralPath[0xFF];
    TCHAR AgainFolder[0xFF];
    TCHAR FileFullPath[0xFF];

    _stprintf(GeneralPath, _T("%s\\*.*"), root);
    hFind = FindFirstFile(GeneralPath, &wfd);

    if(INVALID_HANDLE_VALUE==hFind)
        return;

    do
    {
        if( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) //Checking Founded File Attribute is it File or Folder/Directory
        {
            if( !_tcscmp(wfd.cFileName, _T(".")) || !_tcscmp(wfd.cFileName, _T("..")) ) //if Founded directory is same(.) or parent(..) then ignore them
                continue;
            _stprintf(AgainFolder, _T("%s\\%s"), root, wfd.cFileName);
            Enum(AgainFolder); //Recursion because folder is inside another folder
        }
        else
        {
            _stprintf(FileFullPath, _T("%s\\%s"), root, wfd.cFileName); //  "Folder\\fileName.extension"
            _tprintf(_T("%s\n"),FileFullPath); 
        }

    }while(FindNextFile(hFind, &wfd));

    CloseHandle(hFind);
    hFind=INVALID_HANDLE_VALUE;
}
int main()
{
    TCHAR Folder[0xFF]=_T("c:\\windows");
    Enum(Folder);
    return 0;
}

Si vous souhaitez accéder à la solution complète de Visual Studio, vous pouvez cloner ce dépôt.


3 commentaires

Hey, je voulais changer le _T () ce paramètre avec une chaîne comme ............... string s = "C: \\ test" _T (s) mais cela montre une erreur. ... existe-t-il un moyen de le faire ...


vous devez modifier les paramètres du projet pour utiliser le jeu de caractères comme ascii [propriétés du projet -> propriétés de configuration -> général -> jeu de caractères]


Remplacez ensuite tous les _T (s) par s