2010-01-10 66 views
6

最終,我希望瀏覽文件夾的文件和子目錄,並將所有文件寫入我找到的具有特定擴展名(.wav)的文件。循環時我該如何判斷我所在的項目是否是一個目錄?如何在Windows上遞歸遍歷C中的目錄

+0

遍歷目錄是依賴於操作系統的,所以你可能需要告訴我們您正在使用什麼操作系統。有一些操作系統無關的庫。如果您正在使用其中之一,我們需要知道哪個可以給出一個好的答案。 – 2010-01-10 22:34:08

+0

這是一個UNIX-y平臺(Mac等)或Windows,還是其他的東西?許多平臺都支持POSIX標準(http://robot.mbhs.edu/wordpress/2009/how-to-get-a-directory-listing-in-c-posix/),但通常也會有它們的自己的方式做到這一點,特別是Windows(FindFirstFile/FindNextFile) – 2010-01-10 22:34:17

+0

我還沒有得到這個工作,我想要的。 FindFirstFile正在輸出我所在目錄的名稱,而不是目錄中的第一個文件,如果我離開尾部/。如果我確實把尾部/它給了我一個奇怪的文件名(aaaaa-LIBVC ...)。此外,這兩次FindNextFile不會返回任何值 – pmilb 2010-01-11 01:45:26

回答

0

執行opendir和readdir的(在UNIX上),這裏有一個例子:

http://opengroup.org/onlinepubs/007908775/xsh/readdir.html

或用FindFirstFile在Windows

,你也可以使用殼很容易:

find . -name "*.wav" 

or 

ls **/*.wav (in zsh and newer bashes) 
+0

哎呀,忘了說我也是這樣做的windoze。 – pmilb 2010-01-10 22:36:45

3

基礎的在您提及.wav時,我會猜測您正在編寫Windows代碼(這似乎是*.wav文件是最常見的)。在這種情況下,您使用FindFirstFileFindNextFile來遍歷目錄。這些使用WIN32_FIND_DATA結構,該結構的成員dwFileAttributes包含標識文件屬性的標誌。如果dwAttributes & FILE_ATTRIBUTE_DIRECTORY不爲零,則表示目錄的名稱。

+0

是的,我在Windows上這樣做。我的C真的很生疏,還沒有用C語言編程幾年。我試圖使用dirent.h,但我不認爲它提供任何方式來告訴如果該項目是否是一個目錄。從google找不到一個很好的FindFirstFile示例 – pmilb 2010-01-10 22:46:23

+0

本頁顯示瞭如何使用它們(在VB中,但對C的轉換應該更簡單一些):http://support.microsoft.com/kb/185476。 請注意,您可能還想考慮如何管理NTFS連接點,即是否遵循這些連接點,以及如何避免無限循環。 – Carsten 2010-01-10 22:47:16

7

這裏是你如何做到這一點(這是所有從內存中,因此有可能是錯誤的):

void FindFilesRecursively(LPCTSTR lpFolder, LPCTSTR lpFilePattern) 
{ 
    TCHAR szFullPattern[MAX_PATH]; 
    WIN32_FIND_DATA FindFileData; 
    HANDLE hFindFile; 
    // first we are going to process any subdirectories 
    PathCombine(szFullPattern, lpFolder, _T("*")); 
    hFindFile = FindFirstFile(szFullPattern, &FindFileData); 
    if(hFindFile != INVALID_HANDLE_VALUE) 
    { 
     do 
     { 
      if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
      { 
       // found a subdirectory; recurse into it 
       PathCombine(szFullPattern, lpFolder, FindFileData.cFileName); 
       FindFilesRecursively(szFullPattern, lpFilePattern); 
      } 
     } while(FindNextFile(hFindFile, &FindFileData)); 
     FindClose(hFindFile); 
    } 

    // Now we are going to look for the matching files 
    PathCombine(szFullPattern, lpFolder, lpFilePattern); 
    hFindFile = FindFirstFile(szFullPattern, &FindFileData); 
    if(hFindFile != INVALID_HANDLE_VALUE) 
    { 
     do 
     { 
      if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
      { 
       // found a file; do something with it 
       PathCombine(szFullPattern, lpFolder, FindFileData.cFileName); 
       _tprintf_s(_T("%s\n"), szFullPattern); 
      } 
     } while(FindNextFile(hFindFile, &FindFileData)); 
     FindClose(hFindFile); 
    } 
} 

所以,你可以調用這個像

FindFilesRecursively(_T("C:\\WINDOWS"), _T("*.wav")); 

找到所有的* .wav C:\ WINDOWS及其子目錄中的文件。從技術上講,你不必做兩次FindFirstFile()調用,但是我發現Microsoft提供的模式匹配函數(即PathMatchFileSpec或其他)不如FindFirstFile()。雖然對於「* .wav」,它可能會很好。

+0

@盧克 - 偉大的功能。 – Abhineet 2012-09-13 10:26:32

+0

謝謝!除了一些小的typeos它很好。 – 2013-01-12 19:08:05

+1

'除了一些小型文字,它的效果很好。@ @NeilWeicher有一個編輯按鈕,這樣你就可以修復這些小錯別字。 – Synetech 2015-07-18 18:20:28

1

非常有幫助。 無論如何,我總是添加「。」,因此堆棧溢出。到路徑並返回到相同的路徑=無限循環。

添加此解決它:

// found a subdirectory; recurse into it PathCombine(szFullPattern, lpFolder, FindFileData.cFileName); FindFilesRecursively(szFullPattern, lpPattern); if (FindFileData.cFileName[0] == '.') continue;

+0

這將排除以句點開頭的* all *目錄(包括來自* nix系統的隱藏目錄)。 – Synetech 2015-07-18 18:43:14