¿Cómo puedo obtener la lista de archivos en un directorio usando C o C++?


¿Cómo puedo determinar la lista de archivos en un directorio desde mi código C o C++?

No se me permite ejecutar el comando ls y analizar los resultados desde mi programa.

Author: samoz, 2009-03-04

24 answers

En tareas pequeñas y simples no uso boost, uso dirent.h que también está disponible para windows:

DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\src\\")) != NULL) {
  /* print all the files and directories within directory */
  while ((ent = readdir (dir)) != NULL) {
    printf ("%s\n", ent->d_name);
  }
  closedir (dir);
} else {
  /* could not open directory */
  perror ("");
  return EXIT_FAILURE;
}

Es solo un pequeño archivo de encabezado y hace la mayoría de las cosas simples que necesita sin usar un gran enfoque basado en plantillas como boost (sin ofender, me gusta boost!).

El autor de la capa de compatibilidad de Windows es Toni Ronkko. En Unix, es una cabecera estándar.

ACTUALIZAR 2017:

En C++17 ahora hay una forma oficial de listar archivos de su sistema de archivos: std::filesystem. Hay una excelente respuesta de Shreevardhan abajo con este código fuente:

#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main()
{
    std::string path = "/path/to/directory";
    for (auto & p : fs::directory_iterator(path))
        std::cout << p << std::endl;
}

Considere votar a favor de su respuesta, si está utilizando el enfoque de C++17.

 634
Author: Peter Parker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-14 09:51:47

Desafortunadamente el estándar C++ no define una forma estándar de trabajar con archivos y carpetas de esta manera.

Dado que no hay una forma multiplataforma, la mejor forma multiplataforma es usar una biblioteca como el módulo boost filesystem.

Método de refuerzo multiplataforma:

La siguiente función, dada una ruta de directorio y un nombre de archivo, busca recursivamente el directorio y sus subdirectorios para el nombre del archivo, devolviendo un bool, y si tiene éxito, la ruta al archivo que se encontró.

bool find_file(const path & dir_path,         // in this directory,
               const std::string & file_name, // search for this name,
               path & path_found)             // placing path here if found
{
    if (!exists(dir_path)) 
        return false;

    directory_iterator end_itr; // default construction yields past-the-end

    for (directory_iterator itr(dir_path); itr != end_itr; ++itr)
    {
        if (is_directory(itr->status()))
        {
            if (find_file(itr->path(), file_name, path_found)) 
                return true;
        }
        else if (itr->leaf() == file_name) // see below
        {
            path_found = itr->path();
            return true;
        }
    }
    return false;
}

Fuente de la página boost mencionada anteriormente.


Para sistemas basados en Unix / Linux:

Se puede utilizar opendir / readdir / closedir.

El código de ejemplo que busca un directorio para la entrada "nombre" es:

   len = strlen(name);
   dirp = opendir(".");
   while ((dp = readdir(dirp)) != NULL)
           if (dp->d_namlen == len && !strcmp(dp->d_name, name)) {
                   (void)closedir(dirp);
                   return FOUND;
           }
   (void)closedir(dirp);
   return NOT_FOUND;

Código fuente de las páginas man anteriores.


Para sistemas basados en windows:

Puede utilizar la API de Win32 FindFirstFile / FindNextFile / FindClose funciones.

El siguiente ejemplo de C++ muestra un uso mínimo de FindFirstFile.

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

void _tmain(int argc, TCHAR *argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;

   if( argc != 2 )
   {
      _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
      return;
   }

   _tprintf (TEXT("Target file is %s\n"), argv[1]);
   hFind = FindFirstFile(argv[1], &FindFileData);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("FindFirstFile failed (%d)\n", GetLastError());
      return;
   } 
   else 
   {
      _tprintf (TEXT("The first file found is %s\n"), 
                FindFileData.cFileName);
      FindClose(hFind);
   }
}

Código fuente de las páginas msdn anteriores.

 213
Author: Brian R. Bondy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-29 20:30:42

C++17 ahora tiene un std::filesystem::directory_iterator, que puede utilizarse como

#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main()
{
    std::string path = "/path/to/directory";
    for (const auto & p : fs::directory_iterator(path))
        std::cout << p << std::endl; // "p" is the directory entry. Get the path with "p.path()".
}

También, std::filesystem::recursive_directory_iterator puede iterar los subdirectorios también.

 191
Author: Shreevardhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 17:04:50

Una función es suficiente, no necesita usar ninguna biblioteca de terceros (para Windows).

#include <Windows.h>

vector<string> get_all_files_names_within_folder(string folder)
{
    vector<string> names;
    string search_path = folder + "/*.*";
    WIN32_FIND_DATA fd; 
    HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd); 
    if(hFind != INVALID_HANDLE_VALUE) { 
        do { 
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
                names.push_back(fd.cFileName);
            }
        }while(::FindNextFile(hFind, &fd)); 
        ::FindClose(hFind); 
    } 
    return names;
}

PD: como menciona @Sebastian, puede cambiar *.* a *.ext para obtener solo los archivos EXT (es decir, de un tipo específico) en ese directorio.

 75
Author: herohuyongtao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-12 04:35:40

Para una solución única de C, por favor revise esto. Solo requiere un encabezado adicional:

Https://github.com/cxong/tinydir

tinydir_dir dir;
tinydir_open(&dir, "/path/to/dir");

while (dir.has_next)
{
    tinydir_file file;
    tinydir_readfile(&dir, &file);

    printf("%s", file.name);
    if (file.is_dir)
    {
        printf("/");
    }
    printf("\n");

    tinydir_next(&dir);
}

tinydir_close(&dir);

Algunas ventajas sobre otras opciones:

  • Es portátil-envuelve POSIX dirent y Windows FindFirstFile
  • Utiliza readdir_r cuando está disponible, lo que significa que es (generalmente) threadsafe
  • Soporta Windows UTF-16 a través de las mismas macros UNICODE
  • Es C90 por lo que incluso compiladores muy antiguos pueden usarlo
 44
Author: congusbongus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-17 07:37:37

Recomiendo usar glob con este envoltorio reutilizable. Genera un vector<string> correspondiente a las rutas de archivo que se ajustan al patrón glob:

#include <glob.h>
#include <vector>
using std::vector;

vector<string> globVector(const string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    vector<string> files;
    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
        files.push_back(string(glob_result.gl_pathv[i]));
    }
    globfree(&glob_result);
    return files;
}

Que luego se puede llamar con un patrón comodín del sistema normal como:

vector<string> files = globVector("./*");
 26
Author: Chris Redford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-13 13:40:28

Aquí hay un código muy simple en C++11 usando la biblioteca boost::filesystem para obtener nombres de archivos en un directorio (excluyendo nombres de carpetas):

#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;

int main()
{
    path p("D:/AnyFolder");
    for (auto i = directory_iterator(p); i != directory_iterator(); i++)
    {
        if (!is_directory(i->path())) //we eliminate directories
        {
            cout << i->path().filename().string() << endl;
        }
        else
            continue;
    }
}

La salida es como:

file1.txt
file2.dat
 19
Author: Bad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-25 16:51:30

¿por Qué no usar glob()?

#include <glob.h>

glob_t glob_result;
glob("/your_directory/*",GLOB_TILDE,NULL,&glob_result);
for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
  cout << glob_result.gl_pathv[i] << endl;
}
 17
Author: Meekohi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-15 15:03:46

Creo que, a continuación fragmento se puede utilizar para enumerar todos los archivos.

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

static void list_dir(const char *path)
{
    struct dirent *entry;
    DIR *dir = opendir(path);
    if (dir == NULL) {
        return;
    }

    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n",entry->d_name);
    }

    closedir(dir);
}

A continuación se muestra la estructura de la estructura dirent

struct dirent {
    ino_t d_ino; /* inode number */
    off_t d_off; /* offset to the next dirent */
    unsigned short d_reclen; /* length of this record */
    unsigned char d_type; /* type of file */
    char d_name[256]; /* filename */
};
 15
Author: Shrikant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-26 11:17:48

Prueba boost para el método x-platform

Http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm

O simplemente use el archivo específico de su sistema operativo.

 10
Author: Tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-04 19:37:54

Echa un vistazo a esta clase que utiliza la api win32. Simplemente construya una instancia proporcionando el foldername desde el que desea el listado y luego llame al método getNextFile para obtener el siguiente filename del directorio. Creo que necesita windows.h y stdio.h.

class FileGetter{
    WIN32_FIND_DATAA found; 
    HANDLE hfind;
    char folderstar[255];       
    int chk;

public:
    FileGetter(char* folder){       
        sprintf(folderstar,"%s\\*.*",folder);
        hfind = FindFirstFileA(folderstar,&found);
        //skip .
        FindNextFileA(hfind,&found);        
    }

    int getNextFile(char* fname){
        //skips .. when called for the first time
        chk=FindNextFileA(hfind,&found);
        if (chk)
            strcpy(fname, found.cFileName);     
        return chk;
    }

};
 8
Author: robertvarga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-25 06:40:40

Manual de GNU FTW

Http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister

También, a veces es bueno ir directamente a la fuente (juego de palabras). Puede aprender mucho mirando las entrañas de algunos de los comandos más comunes en Linux. He creado un simple espejo de los coreutils de GNU en github (para leer).

Https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c

Tal vez esto no se dirige a Windows, pero se pueden tener varios casos de uso de variantes de Unix usando estos métodos.

Espero que eso ayude...

 6
Author: Homer6,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-11 21:35:12
char **getKeys(char *data_dir, char* tablename, int *num_keys)
{
    char** arr = malloc(MAX_RECORDS_PER_TABLE*sizeof(char*));
int i = 0;
for (;i < MAX_RECORDS_PER_TABLE; i++)
    arr[i] = malloc( (MAX_KEY_LEN+1) * sizeof(char) );  


char *buf = (char *)malloc( (MAX_KEY_LEN+1)*sizeof(char) );
snprintf(buf, MAX_KEY_LEN+1, "%s/%s", data_dir, tablename);

DIR* tableDir = opendir(buf);
struct dirent* getInfo;

readdir(tableDir); // ignore '.'
readdir(tableDir); // ignore '..'

i = 0;
while(1)
{


    getInfo = readdir(tableDir);
    if (getInfo == 0)
        break;
    strcpy(arr[i++], getInfo->d_name);
}
*(num_keys) = i;
return arr;
}
 4
Author: JasonYen2205,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-29 21:12:31

Espero que este código te ayude.

#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

string wchar_t2string(const wchar_t *wchar)
{
    string str = "";
    int index = 0;
    while(wchar[index] != 0)
    {
        str += (char)wchar[index];
        ++index;
    }
    return str;
}

wchar_t *string2wchar_t(const string &str)
{
    wchar_t wchar[260];
    int index = 0;
    while(index < str.size())
    {
        wchar[index] = (wchar_t)str[index];
        ++index;
    }
    wchar[index] = 0;
    return wchar;
}

vector<string> listFilesInDirectory(string directoryName)
{
    WIN32_FIND_DATA FindFileData;
    wchar_t * FileName = string2wchar_t(directoryName);
    HANDLE hFind = FindFirstFile(FileName, &FindFileData);

    vector<string> listFileNames;
    listFileNames.push_back(wchar_t2string(FindFileData.cFileName));

    while (FindNextFile(hFind, &FindFileData))
        listFileNames.push_back(wchar_t2string(FindFileData.cFileName));

    return listFileNames;
}

void main()
{
    vector<string> listFiles;
    listFiles = listFilesInDirectory("C:\\*.txt");
    for each (string str in listFiles)
        cout << str << endl;
}
 3
Author: Yas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-19 18:22:37

Esta implementación realiza su propósito, llenando dinámicamente una matriz de cadenas con el contenido del directorio especificado.

int exploreDirectory(const char *dirpath, char ***list, int *numItems) {
    struct dirent **direntList;
    int i;
    errno = 0;

    if ((*numItems = scandir(dirpath, &direntList, NULL, alphasort)) == -1)
        return errno;

    if (!((*list) = malloc(sizeof(char *) * (*numItems)))) {
        fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath);
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < *numItems; i++) {
        (*list)[i] = stringDuplication(direntList[i]->d_name);
    }

    for (i = 0; i < *numItems; i++) {
        free(direntList[i]);
    }

    free(direntList);

    return 0;
}
 2
Author: Giacomo Marciani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-13 15:08:17

Esto funciona para mí. Lo siento si no puedo recordar la fuente. Probablemente es de una página de manual.

#include <ftw.h>

int AnalizeDirectoryElement (const char *fpath, 
                            const struct stat *sb,
                            int tflag, 
                            struct FTW *ftwbuf) {

  if (tflag == FTW_F) {
    std::string strFileName(fpath);

    DoSomethingWith(strFileName);
  }
  return 0; 
}

void WalkDirectoryTree (const char * pchFileName) {

  int nFlags = 0;

  if (nftw(pchFileName, AnalizeDirectoryElement, 20, nFlags) == -1) {
    perror("nftw");
  }
}

int main() {
  WalkDirectoryTree("some_dir/");
}
 2
Author: ENHering,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-22 04:44:07

La respuesta de Shreevardhan funciona muy bien. Pero si quieres usarlo en c++14 solo haz un cambio namespace fs = experimental::filesystem;

Es decir,

#include <string>
#include <iostream>
#include <filesystem>

using namespace std;
namespace fs = experimental::filesystem;

int main()
{
    string path = "C:\\splits\\";
    for (auto & p : fs::directory_iterator(path))
        cout << p << endl;
    int n;
    cin >> n;
}
 2
Author: Venkat Vinay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-13 06:38:01

Puedes obtener todos los archivos directos de tu directorio raíz usando std::experimental:: filesystem::directory_iterator(). Luego, lea el nombre de estos archivos de ruta.

#include <iostream>
#include <filesystem>
#include <string>
#include <direct.h>
using namespace std;
namespace fs = std::experimental::filesystem;
void ShowListFile(string path)
{
for(auto &p: fs::directory_iterator(path))  /*get directory */
     cout<<p.path().filename()<<endl;   // get file name
}

int main() {

ShowListFile("C:/Users/dell/Pictures/Camera Roll/");
getchar();
return 0;
}
 2
Author: ducPham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-20 18:04:35

Sistema llamarlo!

system( "dir /b /s /a-d * > file_names.txt" );

Entonces simplemente lea el archivo.

EDITAR: Esta respuesta debe considerarse un truco, pero realmente funciona (aunque de una manera específica de la plataforma) si no tiene acceso a soluciones más elegantes.

 1
Author: Catalyst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-15 04:51:12

Esta respuesta debería funcionar para los usuarios de Windows que han tenido problemas para que esto funcione con Visual Studio con cualquiera de las otras respuestas.

  1. Descarga el dirent.archivo h de la página github. Pero es mejor usar el dirent crudo.h archivo y siga mis pasos a continuación (es cómo llegué a trabajar).

    Página de Github para dirent.h para Windows: Página de Github para dirent.h

    Archivo Dirent raw: Dirent Raw.h File

  2. Vaya a su proyectar y Añadir un nuevo elemento (Ctrl+Shift+A). Añadir un archivo de cabecera (.h) y llámalo dirent.h.

  3. Pegue el dirent raw .h File código en su encabezado.

  4. Incluye " dirent.h " en tu código.

  5. Ponga el siguiente método void filefinder() en su código y llámelo desde su función main o edite la función como desea usarla.

    #include <stdio.h>
    #include <string.h>
    #include "dirent.h"
    
    string path = "C:/folder"; //Put a valid path here for folder
    
    void filefinder()
    {
        DIR *directory = opendir(path.c_str());
        struct dirent *direntStruct;
    
        if (directory != NULL) {
            while (direntStruct = readdir(directory)) {
                printf("File Name: %s\n", direntStruct->d_name); //If you are using <stdio.h>
                //std::cout << direntStruct->d_name << std::endl; //If you are using <iostream>
            }
        }
        closedir(directory);
    }
    
 1
Author: ZKR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-04 00:49:01

Dado que los archivos y subdirectorios de un directorio generalmente se almacenan en una estructura de árbol, una forma intuitiva es usar el algoritmo DFS para recorrer recursivamente cada uno de ellos. Aquí hay un ejemplo en el sistema operativo Windows mediante el uso de funciones de archivo básicas en io.h. Puede reemplazar estas funciones en otra plataforma. Lo que quiero expresar es que la idea básica de DFS resuelve perfectamente este problema.

#include<io.h>
#include<iostream.h>
#include<string>
using namespace std;

void TraverseFilesUsingDFS(const string& folder_path){
   _finddata_t file_info;
   string any_file_pattern = folder_path + "\\*";
   intptr_t handle = _findfirst(any_file_pattern.c_str(),&file_info);
   //If folder_path exsist, using any_file_pattern will find at least two files "." and "..", 
   //of which "." means current dir and ".." means parent dir
   if (handle == -1){
       cerr << "folder path not exist: " << folder_path << endl;
       exit(-1);
   }
   //iteratively check each file or sub_directory in current folder
   do{
       string file_name=file_info.name; //from char array to string
       //check whtether it is a sub direcotry or a file
       if (file_info.attrib & _A_SUBDIR){
            if (file_name != "." && file_name != ".."){
               string sub_folder_path = folder_path + "\\" + file_name;                
               TraverseFilesUsingDFS(sub_folder_path);
               cout << "a sub_folder path: " << sub_folder_path << endl;
            }
       }
       else
            cout << "file name: " << file_name << endl;
    } while (_findnext(handle, &file_info) == 0);
    //
    _findclose(handle);
}
 0
Author: tkingcer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-11 06:57:30

Traté de seguir el ejemplo dado en ambos responde y vale la pena señalar que parece que std::filesystem::directory_entry se ha cambiado para no tener una sobrecarga del operador <<. En lugar de std::cout << p << std::endl; tuve que usar lo siguiente para poder compilar y hacerlo funcionar:

#include <iostream>
#include <filesystem>
#include <string>
namespace fs = std::filesystem;

int main() {
    std::string path = "/path/to/directory";
    for(const auto& p : fs::directory_iterator(path))
        std::cout << p.path() << std::endl;
}

Intentar pasar p por sí solo a std::cout << resultó en un error de sobrecarga faltante.

 0
Author: StarKiller4011,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-25 14:50:54

Solo algo que quiero compartir y gracias por el material de lectura. Juega un poco con la función para entenderla. Puede que te guste. e significa extensión, p es ruta y s es separador de ruta.

Si se pasa la ruta sin terminar separador, se añadirá un separador a la ruta. Para la extensión, si se introduce una cadena vacía, la función devolverá cualquier archivo que no tenga una extensión en su nombre. Si una sola estrella fue introducida que se devolverán todos los archivos del directorio. Si la longitud de e es mayor que 0 pero no es un solo*, entonces un punto se antepondrá a e si e no había contenido un punto en la posición cero.

Para un valor devuelto. Si se devuelve un mapa de longitud cero, entonces no se encontró nada, pero el directorio estaba abierto. Si el índice 999 está disponible desde el valor devuelto, pero el tamaño del mapa es solo 1, eso significa que hubo un problema con la apertura de la ruta del directorio.

Tenga en cuenta que para la eficiencia, esto la función se puede dividir en 3 funciones más pequeñas. Además de eso, puede crear una función de llamada que detectará qué función va a llamar en función de la entrada. ¿Por qué es más eficiente? Dicho esto, si vas a agarrar todo lo que es un archivo, haciendo ese método, la subfunción que se construyó para agarrar todos los archivos simplemente tomará todos los que son archivos y no necesita evaluar ninguna otra condición innecesaria cada vez que encuentre un archivo.

Eso también se aplicaría a cuando agarra archivos que no tengan una extensión. Una función específica construida para ese propósito solo evaluaría para el tiempo si el objeto encontrado es un archivo y luego si el nombre del archivo tiene un punto en él.

El ahorro puede no ser mucho si solo lee directorios con no tantos archivos. Pero si está leyendo una cantidad masiva de directorio o si el directorio tiene un par de cientos de miles de archivos, podría ser un gran ahorro.

#include <stdio.h>
#include <sys/stat.h>
#include <iostream>
#include <dirent.h>
#include <map>

std::map<int, std::string> getFile(std::string p, std::string e = "", unsigned char s = '/'){
    if ( p.size() > 0 ){
        if (p.back() != s) p += s;
    }
    if ( e.size() > 0 ){
        if ( e.at(0) != '.' && !(e.size() == 1 && e.at(0) == '*') ) e = "." + e;
    }

    DIR *dir;
    struct dirent *ent;
    struct stat sb;
    std::map<int, std::string> r = {{999, "FAILED"}};
    std::string temp;
    int f = 0;
    bool fd;

    if ( (dir = opendir(p.c_str())) != NULL ){
        r.erase (999);
        while ((ent = readdir (dir)) != NULL){
            temp = ent->d_name;
            fd = temp.find(".") != std::string::npos? true : false;
            temp = p + temp;

            if (stat(temp.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)){
                if ( e.size() == 1 && e.at(0) == '*' ){
                    r[f] = temp;
                    f++;
                } else {
                    if (e.size() == 0){
                        if ( fd == false ){
                            r[f] = temp;
                            f++;
                        }
                        continue;
                    }

                    if (e.size() > temp.size()) continue;

                    if ( temp.substr(temp.size() - e.size()) == e ){
                        r[f] = temp;
                        f++;
                    }
                }
            }
        }

        closedir(dir);
        return r;
    } else {
        return r;
    }
}

void printMap(auto &m){
    for (const auto &p : m) {
        std::cout << "m[" << p.first << "] = " << p.second << std::endl;
    }
}

int main(){
    std::map<int, std::string> k = getFile("./", "");
    printMap(k);
    return 0;
}
 0
Author: Kevin Ng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-01 00:10:23

Esto funcionó para mí. Escribe un archivo con solo los nombres (sin ruta) de todos los archivos. Luego lee ese archivo txt y lo imprime para usted.

void DisplayFolderContent()
    {

        system("dir /n /b * > file_names.txt");
        char ch;
        std::fstream myStream("file_names.txt", std::fstream::in);
        while (myStream.get(ch))
        {
            std::cout << ch;
        }

    }
 -1
Author: Cesar Alejandro Montero Orozco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-28 05:23:35