2012-09-24 150 views
0

我正在嘗試查找所有目錄中的所有文件,但我不知道如何處理子目錄。在這段代碼中,代碼看起來遍歷所有的子代,但我不知道如何跳回來。有誰知道如何做到這一點?在C++中查找所有目錄中的所有文件

__declspec(dllexport) void GetFiles(char* filedir, char* path) 
{ 
    string s[1000]; 
    string path2 = path; 
    UINT index = 0; 

    WIN32_FIND_DATA ffd; 
    TCHAR szDir[MAX_PATH]; 
    HANDLE hFind = INVALID_HANDLE_VALUE; 
    DWORD dwError=0; 

    StringCchCopy(szDir, MAX_PATH, filedir); 

    if (INVALID_HANDLE_VALUE == hFind) 
     return; 

    do 
    { 

     DWORD attributes = ffd.dwFileAttributes; 

     if (attributes & FILE_ATTRIBUTE_HIDDEN) 
      continue; 
     else if (attributes & FILE_ATTRIBUTE_DIRECTORY) 
     { 
      TCHAR dir2[MAX_PATH]; 
      path2 = path; 
      path2 += ffd.cFileName; 
      path2 += "\\*"; 
      StringCchCopy(dir2, MAX_PATH, path2.c_str()); 
      SetCurrentDirectory(dir2); 
     } 
     else 
     { 
      s[index] = path; 
      s[index] += ffd.cFileName; 
      index++; 
     } 
    } 
    while (FindNextFile(hFind, &ffd) >= 0); // needs to jump back if zero 

    FindClose(hFind); 
} 

編輯:功能有哪些困惑編譯

+3

只要更改當前目錄,將不會更改「FindFirstFile」和「FindNextFile」搜索的位置。您可以通過遞歸地使用相同的函數來搜索子目錄,也可以先執行廣度優先搜索,但保留需要搜索的目錄隊列(其中,當遇到目錄時,只需將其推入隊列中) 。 –

+0

你可能想要防範「。」和「..」,因爲他們傾向於(實際上*將*)導致無限枚舉。 – WhozCraig

回答

1

而不是通過SetCurrentDirectory()改變目錄使用遞歸調用GetFiles()。這將要求調用者傳遞對數組(或std::vector<std::string>)的引用以獲取要存儲的文件列表,而不是使用本地數組s

0

我看看升壓的目錄,而不是迭代器相同的名稱。

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

有例子覆蓋你正在嘗試做的,它會爲幾乎所有你能想到的任何操作系統中使用。

查看示例3.它顯示如何遍歷目錄的所有內容。如果你發現了一個你以前從未見過的新目錄,那麼你只需要做同樣的事情。有測試告訴你,如果文件是常規的,目錄等,所以試試看。

2

我認爲最簡單的方法就是做一個遞歸函數。

這大致模樣在「C」僞代碼

void GetFiles(char*** file_path_table, char* dir) 
{ 
    char **file_paths; 
    file_paths = getAllFiles(dir); 
    foreach(path in file_paths) 
    { 
     if (is_directory(path)) 
     { 
      GetFiles(file_path_table, path); 
     } 
     else 
     { 
      add_file_to_table(file_path_table, path); 
     } 
    } 
} 
+1

'is_directory()'是否會檢測指向目錄的符號鏈接,使其回到同一棵樹的較高位置(有效地使您的樹成爲圖形)? –

+0

這將是具體實現,並取決於你想要做什麼。如果您想遵循符號鏈接,則應該進行檢查以避免觸發無限循環。 – TheThibz

1

做了一些通過舊帖子搜索的這樣的事情,我想我已經提到一個廣度優先搜索一些的時代,但從來沒有真正發佈代碼來展示如何去做。我想我可能會這麼做。

#include <windows.h> 
#include <queue> 
#include <string> 
#include <iostream> 

// I think MS's names for some things are obnoxious. 
const HANDLE HNULL = INVALID_HANDLE_VALUE; 
const int A_DIR = FILE_ATTRIBUTE_DIRECTORY; 

// We'll process a file by printing its path/name 
void process(std::string const &path, WIN32_FIND_DATA const &file) { 
    std::cout << path << file.cFileName << "\n"; 
} 

void find_file(std::string const &folder_name, std::string const &fmask) { 
    HANDLE finder;   // for FindFirstFile 
    WIN32_FIND_DATA file; // data about current file. 
    std::priority_queue<std::string, std::vector<std::string>, 
         std::greater<std::string> > dirs; 
    dirs.push(folder_name); // start with passed directory 

    do { 
     std::string path = dirs.top();// retrieve directory to search 
     dirs.pop(); 

     if (path[path.size()-1] != '\\') // normalize the name. 
      path += "\\"; 

     std::string mask = path + fmask; // create mask for searching 

     // traverse a directory. Search for sub-dirs separately, because we 
     // don't want a mask to apply to directory names. "*.cpp" should find 
     // "a\b.cpp", even though "a" doesn't match "*.cpp". 
     // 
     // First search for files: 
     if (HNULL==(finder=FindFirstFile(mask.c_str(), &file))) 
      continue; 

     do { 
      if (!(file.dwFileAttributes & A_DIR)) 
       process(path, file); 
     } while (FindNextFile(finder, &file)); 
     FindClose(finder); 

     // Then search for subdirectories: 
     if (HNULL==(finder=FindFirstFile((path + "*").c_str(), &file))) 
      continue; 
     do { 
      if ((file.dwFileAttributes & A_DIR) && (file.cFileName[0] != '.')) 
       dirs.push(path + file.cFileName); 
     } while (FindNextFile(finder, &file)); 
     FindClose(finder); 
    } while (!dirs.empty()); 
} 

int main(int argc, char **argv) { 
    if (argc > 2) 
     find_file(argv[1], argv[2]); 
    else 
     find_file("C:\\", "*"); 
    return 0; 
} 
1

爲什麼不使用增強recursive_directory_iterator

注意:未經測試(但應該看起來像這樣)。

namespace bfs = boost::filesystem; 

std::vector<std::string> filenames; 

std::copy(bfs::recursive_directory_iterator("<path>"), 
      bfs::recursive_directory_iterator(), 
      std::back_inserter(filenames) 
     ); 
相關問題