2010-12-29 18 views
18

Estoy escribiendo un programa para verificar si algo es un archivo o es un directorio. ¿Hay una mejor manera de hacerlo que esto?Comprobando si un archivo es un directorio o solo un archivo

#include <stdio.h> 

#include <sys/types.h> 
#include <dirent.h> 
#include <errno.h> 

int isFile(const char* name) 
{ 
    DIR* directory = opendir(name); 

    if(directory != NULL) 
    { 
    closedir(directory); 
    return 0; 
    } 

    if(errno == ENOTDIR) 
    { 
    return 1; 
    } 

    return -1; 
} 

int main(void) 
{ 
    const char* file = "./testFile"; 
    const char* directory = "./"; 

    printf("Is %s a file? %s.\n", file, 
    ((isFile(file) == 1) ? "Yes" : "No")); 

    printf("Is %s a directory? %s.\n", directory, 
    ((isFile(directory) == 0) ? "Yes" : "No")); 

    return 0; 
} 

Respuesta

36

Puede llamar a la función stat() y utilizar la macro S_ISREG() en el campo de la estructura statst_mode con el fin de determinar si sus puntos de ruta a un archivo normal:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 

int is_regular_file(const char *path) 
{ 
    struct stat path_stat; 
    stat(path, &path_stat); 
    return S_ISREG(path_stat.st_mode); 
} 

Tenga en cuenta que existen otros tipos de archivos, además de Regula r y directorio, como dispositivos, tuberías, enlaces simbólicos, enchufes, etc. Es posible que desee tenerlos en cuenta.

+4

Al considerar casos de enlace simbólico, use lstat() en lugar de stat() ya que no sigue el enlace simbólico. – Sparky

+3

Hay al menos una buena discusión en [Comprobando si existe un directorio] (http://stackoverflow.com/questions/3828192/checking-if-a-directory-exists-in-unix-system-call/), donde ' stat() 'y' lstat() 'se discuten y se describe el conjunto completo de tipos de archivos POSIX. Estoy tentado de duplicar esta pregunta a ese. El código también debe verificar el resultado de 'stat()' y manejar los errores de manera apropiada. –

+0

@Jonathan, esa respuesta es de hecho más completa que la mía, y fue publicada tres meses antes que la mía, hace cinco años. Y no es como si mi propia respuesta desapareciera de todos modos. Veo que empuñas a Mjölnir en la etiqueta '[c]', así que gracias por comentar antes de actuar unilateralmente. Sin embargo, finalmente tienes razón. No se preocupe, haga lo que tiene que hacer :) –

4

Sí, hay mejores. Compruebe el stat o la función fstat

14

Utilice la S_ISDIR macro:

int isDirectory(const char *path) { 
    struct stat statbuf; 
    if (stat(path, &statbuf) != 0) 
     return 0; 
    return S_ISDIR(statbuf.st_mode); 
} 
+0

Olvidó completar la estructura 'statbuf' con información. – RedX

+1

Esto funciona bien tal como está, la función de estadísticas llena la información. – ismail

+2

Idealmente, el código verificaría que 'stat' funcionara:' if (stat (ruta, & statbuf)! = 0) return 0; '- porque un objeto inexistente no es un directorio, y si no tiene el permiso para 'stat()' it, bien podría no existir (incluso si el error informado está relacionado con los permisos). –

1

Normalmente, desea realizar esta comprobación atómicamente con el uso del resultado, por lo que stat() es inútil. En su lugar, open() el archivo es de solo lectura y usa fstat(). Si es un directorio, puede usar fdopendir() para leerlo. O puede intentar abrirlo para escribir, y el abierto fallará si es un directorio. Algunos sistemas (POSIX 2008, Linux) también tienen una extensión de O_DIRECTORY a open que hace que la llamada falle si el nombre no es un directorio.

Su método con opendir() también es bueno si desea un directorio, pero no debe cerrarlo después; deberías seguir y usarlo.

Cuestiones relacionadas