¿Cómo listar archivos en un directorio en un programa C?

88

Estoy intentando escribir un servidor ftp en Linux. En este asunto, ¿cómo puedo listar archivos en el directorio de la terminal mediante un programa en C? Tal vez pueda usar la función exec para ejecutar el comando de búsqueda, pero quiero el nombre del archivo como una cadena para enviar el programa cliente. ¿Cómo puedo hacer esto?

Gracias por las respuestas.

cemal
fuente

Respuestas:

175

Un ejemplo, disponible para sistemas compatibles con POSIX:

/*
 * This program displays the names of all files in the current directory.
 */

#include <dirent.h> 
#include <stdio.h> 

int main(void) {
  DIR *d;
  struct dirent *dir;
  d = opendir(".");
  if (d) {
    while ((dir = readdir(d)) != NULL) {
      printf("%s\n", dir->d_name);
    }
    closedir(d);
  }
  return(0);
}

Tenga en cuenta que dicha operación depende de la plataforma en C.

Fuente: http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1046380353&id=1044780608

Jean-Bernard Jansen
fuente
ahora está bien y es muy fácil. Gracias por responder de nuevo.
cemal
13
por favor valídelo si le gustó;)
Jean-Bernard Jansen
1
Genial, pero ¿y si solo queremos pngarchivos?
Farsheed
2
@Farsheed: prueba esto .
Fraxtil
Encuentro algunos problemas con esto. Primero, "." y ".." aparecen en la parte superior de cada directorio, y aunque son "directorios" tienen el directorio dir-> d_type establecido en DT_REG. Además, parece que no obtengo todos los archivos ... ¿Hay un código de "escáner de directorio" más completo en alguna parte? ¿Quizás alguna implementación pobre de "ls"? Necesito esto en Mac - OS-X
Motti Shneor
35

Una pequeña adición a la respuesta de JB Jansen : en el readdir()ciclo principal agregaría esto:

  if (dir->d_type == DT_REG)
  {
     printf("%s\n", dir->d_name);
  }

Solo verificando si es realmente un archivo, no un enlace (simbólico), directorio o lo que sea.

NOTA: más sobre struct direnten la libcdocumentación .

Kamiccolo
fuente
6
Solo un comentario: no todas las plataformas se completarán d_type, pero Linux y BSD sí (sé que la pregunta está etiquetada como Linux, solo extendiendo un poco la respuesta); incluso entonces, no todos los sistemas de archivos son compatibles de manera uniforme , sin embargo, debería funcionar con la mayoría de FS.
omninonsense
11

Aquí hay un programa completo sobre cómo enumerar de forma recursiva el contenido de la carpeta:

#include <dirent.h> 
#include <stdio.h> 
#include <string.h>

#define NORMAL_COLOR  "\x1B[0m"
#define GREEN  "\x1B[32m"
#define BLUE  "\x1B[34m"



/* let us make a recursive function to print the content of a given folder */

void show_dir_content(char * path)
{
  DIR * d = opendir(path); // open the path
  if(d==NULL) return; // if was not able return
  struct dirent * dir; // for the directory entries
  while ((dir = readdir(d)) != NULL) // if we were able to read somehting from the directory
    {
      if(dir-> d_type != DT_DIR) // if the type is not directory just print it with blue
        printf("%s%s\n",BLUE, dir->d_name);
      else
      if(dir -> d_type == DT_DIR && strcmp(dir->d_name,".")!=0 && strcmp(dir->d_name,"..")!=0 ) // if it is a directory
      {
        printf("%s%s\n",GREEN, dir->d_name); // print its name in green
        char d_path[255]; // here I am using sprintf which is safer than strcat
        sprintf(d_path, "%s/%s", path, dir->d_name);
        show_dir_content(d_path); // recall with the new path
      }
    }
    closedir(d); // finally close the directory
}

int main(int argc, char **argv)
{

  printf("%s\n", NORMAL_COLOR);

    show_dir_content(argv[1]);

  printf("%s\n", NORMAL_COLOR);
  return(0);
}
Faroq AL-Tam
fuente
4

El siguiente código solo imprimirá archivos dentro del directorio y excluirá directorios dentro del directorio dado mientras se recorre.

#include <dirent.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include<string.h>
int main(void)
{
    DIR *d;
    struct dirent *dir;
    char path[1000]="/home/joy/Downloads";
    d = opendir(path);
    char full_path[1000];
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            //Condition to check regular file.
            if(dir->d_type==DT_REG){
                full_path[0]='\0';
                strcat(full_path,path);
                strcat(full_path,"/");
                strcat(full_path,dir->d_name);
                printf("%s\n",full_path);
            }
        }
        closedir(d);
    }
    return(0);     
}
Alegría
fuente