2010-01-10 65 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