2010-01-10 20 views
6

En última instancia, quiero viajar a través de los archivos y subdirectorios de una carpeta y escribir algo en todos los archivos que encuentro que tienen cierta extensión (.wav en mi caso). cuando bucle, ¿cómo puedo saber si el elemento en el que estoy es un directorio?Cómo recorrer recursivamente directorios en C en Windows

+0

directorios de desplazamiento corresponde OS-dependiente, por lo que es probable que tenga que decirnos qué sistema operativo que esté utilizando. Hay algunas librerías independientes del sistema operativo. Si está utilizando uno de ellos, necesitaremos saber a cuál dar una buena respuesta. –

+0

¿Es esta una plataforma UNIX-y (Mac, etc.) o Windows, o algo completamente diferente? Muchas plataformas soportarán los estándares POSIX (http://robot.mbhs.edu/wordpress/2009/how-to-get-a-directory-listing-in-c-posix/), pero también generalmente tendrán su propia forma de hacerlo, especialmente Windows (FindFirstFile/FindNextFile) –

+0

Todavía no estoy obteniendo esto para que funcione como yo quiero. FindFirstFile está dando como resultado el nombre del directorio en el que estoy, no es el primer archivo en el directorio si dejo el final de /. Si pongo el final/its me da un nombre de archivo raro (aaaaa-LIBVC ...).Además, las dos veces FindNextFile no devolverá ningún valor en absoluto – pmilb

Respuesta

0

opendir y readdir (en UNIX), he aquí un ejemplo:

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

o FindFirstFile en las ventanas

también se puede utilizar la cáscara con bastante facilidad:

find . -name "*.wav" 

or 

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

¡Uy !, se olvidó de decir que estoy haciendo esto también en windoze. – pmilb

3

Based en su mención de .wav, voy a adivinar que está escribiendo código para Windows (que parece ser donde *.wav son los archivos más comunes). En este caso, usa FindFirstFile y FindNextFile para recorrer directorios. Estos utilizan una estructura WIN32_FIND_DATA, que tiene un miembro dwFileAttributes que contiene indicadores que indican los atributos del archivo. Si dwAttributes & FILE_ATTRIBUTE_DIRECTORY es distinto de cero, tiene el nombre de un directorio.

+0

Sí, estoy haciendo esto en Windows. Mi C está muy oxidado, no lo he programado en C desde hace unos años. Intenté usar dirent.h, pero no creo que ofrezca ninguna forma de decir si el elemento es un directorio o no. No se puede encontrar un buen ejemplo de FindFirstFile de google – pmilb

+0

Esta página muestra cómo usarlos (en VB, pero la traducción a C debería ser más o menos directa): http://support.microsoft.com/kb/185476. Tenga en cuenta que también le conviene pensar en la forma en que maneja las uniones NTFS, es decir, si las sigue o no, y si desea evitar ciclos infinitos. – Carsten

7

Aquí es cómo lo hace (esto es todo de la memoria lo que puede haber errores):

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); 
    } 
} 

por lo que podría llamar a esto como

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

permite encontrar todos los archivos * .wav archivos en C: \ WINDOWS y sus subdirectorios.

Técnicamente no tiene que hacer dos llamadas a FindFirstFile(), pero creo que las funciones de coincidencia de patrones que proporciona Microsoft (es decir, PathMatchFileSpec o lo que sea) no son tan capaces como FindFirstFile(). Aunque para "* .wav" probablemente estaría bien.

+0

@ Luke- Gran función. – Abhineet

+0

Gracias! Además de un par de typeos menores, funciona genial. –

+1

'Además de un par de tipos menores, funciona genial. @NeilWeicher hay un botón de edición para que pueda corregir esos errores menores. – Synetech

1

de gran ayuda. Tenía de todos modos, un desbordamiento de pila ya que siempre estaba agregando "." a la ruta y regresar a la misma ruta = bucle sin fin.

La adición de este resolvió:

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

+0

Eso excluiría * todos * directorios comenzando con un punto (incluidos los directorios ocultos que provienen de los sistemas * nix). – Synetech

Cuestiones relacionadas