2017-10-05 5 views
0

Je dois obtenir une liste de dossiers dans le répertoire, mais seulement les dossiers. Aucun fichier n'est requis Seuls les dossiers. J'utilise des filtres pour déterminer s'il s'agit d'un dossier, mais ils ne fonctionnent pas et tous les fichiers et dossiers sont sortis.C++ dossier uniquement recherche

string root = "D:\\*"; 
cout << "Scan " << root << endl; 
std::wstring widestr = std::wstring(root.begin(), root.end()); 
const wchar_t* widecstr = widestr.c_str(); 
WIN32_FIND_DATAW wfd; 
HANDLE const hFind = FindFirstFileW(widecstr, &wfd); 

De cette manière, je vérifie que c'est un dossier.

if (INVALID_HANDLE_VALUE != hFind) 
    if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
     if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) 

Comment résoudre un problème?

+0

https://stackoverflow.com/questions/5043403/listing-only-folders-in-directory –

+1

sur JURE #include et sur les fenêtres actuelles ne supportent pas cette DIR – Xom9ik

+1

. vous pouvez vous [[FindFirstFileEx]] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa364419 (v = vs.85) .aspx) avec * fSearchOp * défini sur ['FindExSearchLimitToDirectories' ] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa364416 (v = vs.85) .aspx) - mais ce drapeau n'a aucun effet maintenant – RbMm

Répondre

2

Cette fonction collecte les dossiers dans un vecteur donné. Si vous définissez récursive true, il sera scanner les dossiers dans les dossiers dans les dossiers etc.

// TODO: proper error handling. 

void GetFolders(std::vector<std::wstring>& result, const wchar_t* path, bool recursive) 
{ 
    HANDLE hFind; 
    WIN32_FIND_DATA data; 
    std::wstring folder(path); 
    folder += L"\\"; 
    std::wstring mask(folder); 
    mask += L"*.*"; 

    hFind=FindFirstFile(mask.c_str(),&data); 
    if(hFind!=INVALID_HANDLE_VALUE) 
    { 
     do 
     { 
      std::wstring name(folder); 
      name += data.cFileName; 
      if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
       // I see you don't want FILE_ATTRIBUTE_REPARSE_POINT 
       && !(data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) 
      { 
       // Skip . and .. pseudo folders. 
       if (wcscmp(data.cFileName, L".") != 0 && wcscmp(data.cFileName, L"..") != 0) 
       { 
        result.push_back(name); 
        if (recursive) 
         // TODO: It would be wise to check for cycles! 
         GetFolders(result, name.c_str(), recursive); 
       } 
      } 
     } while(FindNextFile(hFind,&data)); 
    } 
    FindClose(hFind); 
} 

modifié à partir https://stackoverflow.com/a/46511952/8666197

2

Il y a deux façons de le faire: la dure, et la manière facile .

La méthode difficile est basée sur FindFirstFile et FindNextFile, en filtrant les répertoires selon les besoins. Vous trouverez des exemples de bazillion qui décrivent cette approche, à la fois sur Stack Overflow et le reste de l'Internet.

La méthode la plus simple: utilisez la classe standard directory_iterator (ou recursive_directory_iterator, si vous avez besoin de recurrencer dans des sous-répertoires). La solution est aussi simple que :

for (const auto& entry : directory_iterator(path(L"abc"))) { 
    if (is_directory(entry.path())) { 
     // Do something with the entry 
     visit(entry.path()); 
    } 
} 

Vous devrez inclure le fichier d'en-tête <filesystem>, introduit en C++ 17. En utilisant la dernière version de Visual Studio 2017 (15.3.5), ce n'est pas encore namespace std. Vous devrez faire référence à namespace std::experimental::filesystem à la place.


Notez en particulier, qu'il n'y a pas besoin de filtrer les . et .. pseudo-répertoires; ceux-ci ne sont pas retournés par les itérateurs de répertoire.