@chrish - Sí, pero este tiene el clásico "¡No tengo permitido ejecutar el 'ls'"! Es exactamente como me sentiría el primer año de informática. ; D <3 x
James Bedford
1
C y C ++ no son el mismo lenguaje. Por lo tanto, el procedimiento para realizar esta tarea será diferente en ambos idiomas. Elija uno y vuelva a etiquetar en consecuencia.
MD XF
2
Y ninguno de esos lenguajes (aparte de C ++ desde C ++ 17) tiene un concepto de directorio, por lo que es probable que cualquier respuesta dependa de su sistema operativo o de cualquier biblioteca de abstracción que pueda estar utilizando.
Toby Speight
Respuestas:
810
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 un encabezado estándar.
ACTUALIZACIÓN 2017 :
En C ++ 17 ahora hay una forma oficial de archivos de lista de su sistema de archivos: std::filesystem. Hay una excelente respuesta de Shreevardhan a continuación con este código fuente:
@ArtOfWarfare: tinydir ni siquiera se creó cuando se respondió esta pregunta. También es un contenedor alrededor de dirent (POSIX) y FindFirstFile (Windows), mientras que dirent.h simplemente envuelve dirent para Windows. Creo que es un gusto personal, pero directo. Me siento más como un estándar
Peter Parker
77
@JoshC: porque * ent es solo un puntero devuelto de la representación interna. al cerrar el directorio, también eliminará el * ent. Como * ent es solo para leer, creo que este es un diseño sensato.
Peter Parker
42
la gente se vuelve real !! Esta es una pregunta de 2009 y ni siquiera ha mencionado VS. Por lo tanto, no critique que su IDE patentado completo (aunque bastante bueno) no admite estándares de sistema operativo centenarios. También mi respuesta dice que está "disponible" para Windows, no "incluido" en ningún IDE desde ahora y para siempre ... Estoy bastante seguro de que puede descargarlo directamente y ponerlo en algún directorio de inclusión y listo.
Peter Parker
66
La respuesta es engañosa. Debería comenzar con: " ... utilizo dirent.h , para el cual también existe una capa de compatibilidad de código abierto de Windows ".
rustyx
10
Con C ++ 14 existe std::experimental::filesystem, con C ++ 17 existe std::filesystem. Ver la respuesta de Shreevardhan a continuación. Por lo tanto, no necesita bibliotecas de terceros.
AFAIK también se puede utilizar en C ++ 14, pero hay todavía es experimental: namespace fs = std::experimental::filesystem;. Aunque parece funcionar bien.
PeterK
77
Esta debería ser la respuesta preferida para el uso actual (comenzando con C ++ 17)
diodo verde
44
Preste atención al pasar std::filesystem::patha std::cout, las comillas se incluyen en la salida. Para evitar eso, agregue .string()a la ruta para hacer una conversión explícita en lugar de implícita (aquí std::cout << p.string() << std::endl;). Ejemplo: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
Roi Danton el
2
¿Qué pasa con los caracteres NO ASCII en los nombres de archivo? ¿No std::wstringdebería usarse o cuál es el tipo del iterador?
anddero
2
No estoy seguro de si estoy solo en esto, pero sin vincularme -lstdc++fs, obtendría un SIGSEGV (Address boundary error). No pude encontrar en ninguna parte de la documentación que esto fuera necesario, y el enlazador tampoco dio ninguna pista. Esto funcionó para ambos g++ 8.3.0y clang 8.0.0-3. ¿Alguien tiene alguna idea de dónde se especifica este tipo de cosas en los documentos / especificaciones?
swalog
229
Desafortunadamente, el estándar C ++ no define una forma estándar de trabajar con archivos y carpetas de esta manera.
Dado que no existe una forma multiplataforma, la mejor forma multiplataforma es utilizar una biblioteca como el módulo de sistema de archivos boost .
Método de impulso multiplataforma:
La siguiente función, dada una ruta de directorio y un nombre de archivo, busca de forma recursiva el nombre del archivo en el directorio y sus subdirectorios, devuelve 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))returnfalse;
directory_iterator end_itr;// default construction yields past-the-endfor(directory_iterator itr(dir_path); itr != end_itr;++itr){if(is_directory(itr->status())){if(find_file(itr->path(), file_name, path_found))returntrue;}elseif(itr->leaf()== file_name)// see below{
path_found = itr->path();returntrue;}}returnfalse;}
Fuente de la página de impulso mencionada anteriormente.
Con C ++ 14 existe std::experimental::filesystem, con C ++ 17 existe std::filesystem, que tiene una funcionalidad similar a boost (las libs se derivan de boost). Ver la respuesta de Shreevardhan a continuación.
Esta solución es específica de la plataforma. Esa es la razón por la que necesita bibliotecas de terceros.
kraxor
99
@kraxor Sí, solo funciona en Windows, pero OP nunca pide tener una solución multiplataforma. Por cierto, siempre prefiero elegir algo sin usar terceras bibliotecas (si es posible).
herohuyongtao
77
@herohuyongtao OP nunca especificó una plataforma, y dar una solución altamente dependiente de la plataforma a una pregunta genérica puede ser engañoso. (¿Qué pasa si hay una solución de una línea que solo funciona en PlayStation 3? ¿Es una buena respuesta aquí?) Veo que editó su respuesta para indicar que solo funciona en Windows, supongo que está bien de esta manera.
kraxor
1
@herohuyongtao OP mencionó que no puede analizar ls, lo que significa que probablemente esté en Unix ... de todos modos, es una buena respuesta para Windows.
Thomas
2
Terminé usando a std::vector<std::wstring>y luego en fileName.c_str()lugar de un vector de cadenas, que no se compilaría.
PerryC
51
Para una solución única en C, por favor revise esto. Solo requiere un encabezado adicional:
Muy buena sugerencia. Todavía no lo he probado en una computadora con Windows, pero funciona de manera brillante en OS X.
ArtOfWarfare
La biblioteca no admite std :: string, por lo que no puede pasar file.c_str () a tinydir_open. Da el error C2664 durante la compilación en msvc 2015 en este caso.
Stepan Yakovenko
33
Recomiendo usar globcon este envoltorio reutilizable. Genera una ruta vector<string>correspondiente al archivo que se ajusta al patrón global:
Me gustaría usar glob.h como me lo recomendó. Pero aún así, no puedo incluir el archivo .h: dice No such file or directory. ¿Me puede decir cómo resolver este problema, por favor?
Tofuw
Tenga en cuenta que esta rutina solo tiene un nivel de profundidad (sin recursividad). Asimismo, no hacer una rápida comprobación para determinar si se trata de un archivo o directorio, lo que se puede hacer fácilmente por el cambio GLOB_TILDEcon GLOB_TILDE | GLOB_MARKy luego la comprobación de caminos que terminan en una barra. Tendrá que hacer cualquier modificación si lo necesita.
Volomike
¿Es compatible esta plataforma cruzada?
Nikhil Augustine
Lamentablemente no puede encontrar archivos uniformemente ocultos a través de glob.
LmTinyToon
23
Aquí hay un código muy simple al C++11usar la boost::filesystembiblioteca para obtener nombres de archivos en un directorio (excluyendo los nombres de carpetas):
#include<string>#include<iostream>#include<boost/filesystem.hpp>usingnamespace std;usingnamespace 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;}elsecontinue;}}
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 */unsignedshort d_reclen;/* length of this record */unsignedchar d_type;/* type of file */char d_name[256];/* filename */};
Si bien este enlace puede responder la pregunta, es mejor incluir aquí las partes esenciales de la respuesta y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden volverse inválidas si la página vinculada cambia. - De la opinión
ice1000
@ ice1000 ¿En serio? Este Q&A es de 2009
Tim
8
Echa un vistazo a esta clase que usa la API win32. Simplemente construya una instancia proporcionando el nombre foldernamedel cual desea el listado y luego llame al getNextFilemétodo para obtener el siguiente filenamedel directorio. Creo que necesita windows.hy stdio.h.
classFileGetter{
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;}};
Además, a veces es bueno ir directamente a la fuente (juego de palabras). Puedes aprender mucho mirando las entrañas de algunos de los comandos más comunes en Linux. He configurado un espejo simple de los coreutils de GNU en github (para leer).
-1. string2wchar_tdevuelve la dirección de una variable local. Además, probablemente debería usar los métodos de conversión disponibles en WinAPI en lugar de escribir los suyos propios.
Daniel Kamil Kozar
3
Esta implementación cumple su propósito, llenando dinámicamente una serie de cadenas con el contenido del directorio especificado.
int exploreDirectory(constchar*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);return0;}
¿Cómo llamaría esto? Recibo segfaults cuando intento ejecutar esta función en el primer ifbloque. Lo llamo conchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Hal T
2
Esto funciona para mi. Lo siento si no puedo recordar la fuente. Probablemente sea de una página de manual.
puede obtener todos los archivos directos en su directorio raíz utilizando std :: experimental :: filesystem :: directory_iterator (). Luego, lea el nombre de estos archivos de ruta.
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.
Descargue el archivo dirent.h de la página de github. Pero es mejor usar el archivo Raw dirent.h y seguir mis pasos a continuación (así es como lo hice funcionar).
Ponga el siguiente void filefinder()método en su código y llámelo desde su mainfunción o edite la función como quiera usarlo.
#include<stdio.h>#include<string.h>#include"dirent.h"string path ="C:/folder";//Put a valid path here for foldervoid 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);}
EDITAR: esta respuesta debe considerarse un truco, pero realmente funciona (aunque sea de forma específica para la plataforma) si no tiene acceso a soluciones más elegantes.
No se me permite ejecutar el comando 'ls' y analizar los resultados desde mi programa. Sabía que habría alguien que enviaría algo así ...
yyny
1
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 utilizando funciones básicas de archivo en io.h. Puede reemplazar estas funciones en otra plataforma. Lo que quiero expresar es que la idea básica de DFS cumple perfectamente con este problema.
#include<io.h>#include<iostream.h>#include<string>usingnamespace std;voidTraverseFilesUsingDFS(conststring& 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 dirif(handle ==-1){
cerr <<"folder path not exist: "<< folder_path << endl;exit(-1);}//iteratively check each file or sub_directory in current folderdo{string file_name=file_info.name;//from char array to string//check whtether it is a sub direcotry or a fileif(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);}
Traté de seguir el ejemplo dado en ambas respuestas y podría valer la pena señalar que parece que std::filesystem::directory_entryse ha cambiado para no tener una sobrecarga del <<operador. En lugar de std::cout << p << std::endl;tener que usar lo siguiente para poder compilar y hacer que funcione:
Si sabe que solo usará multibyte, podría usar WIN32_FIND_DATAA, FindFirstFileAy FindNextFileA. Entonces no habrá necesidad de convertir el resultado a multibyte o la entrada a unicode.
Kiran Thilak
0
Es algo que quiero compartir y gracias por el material de lectura. Juega un poco con la función para entenderla. Te puede gustar. e representaba la extensión, p es para la ruta y s es para el separador de ruta.
Si la ruta se pasa sin terminar el separador, se agregará un separador a la ruta. Para la extensión, si se ingresa una cadena vacía, la función devolverá cualquier archivo que no tenga una extensión en su nombre. Si se ingresó una sola estrella, 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 hubiera contenido un punto en la posición cero.
Por un valor de retorno. 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 de retorno pero el tamaño del mapa es solo 1, eso significa que hubo un problema al abrir la ruta del directorio.
Tenga en cuenta que, para mayor eficiencia, esta 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á a qué función va a llamar en función de la entrada. ¿Por qué es eso más eficiente? Dijo que si va a capturar todo lo que es un archivo, al hacer ese método, la subfunción que se creó para capturar todos los archivos simplemente capturará todos los archivos y no necesita evaluar ninguna otra condición innecesaria cada vez que encuentra un archivo.
Eso también se aplicaría cuando tomas archivos que no tienen una extensión. Una función construida específica para ese propósito solo evaluaría el clima si el objeto encontrado es un archivo y luego si el nombre del archivo tiene un punto o no.
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 ="",unsignedchar 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(constauto&p : m){
std::cout <<"m["<< p.first <<"] = "<< p.second << std::endl;}}int main(){
std::map<int, std::string> k = getFile("./","");
printMap(k);return0;}
stat()
error 'no existe tal archivo o directorio' cuando el nombre del archivo es devuelto porreaddir()
.Respuestas:
En tareas pequeñas y simples, no uso boost, uso dirent.h, que también está disponible para Windows:
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 un encabezado estándar.
ACTUALIZACIÓN 2017 :
En C ++ 17 ahora hay una forma oficial de archivos de lista de su sistema de archivos:
std::filesystem
. Hay una excelente respuesta de Shreevardhan a continuación con este código fuente:fuente
std::experimental::filesystem
, con C ++ 17 existestd::filesystem
. Ver la respuesta de Shreevardhan a continuación. Por lo tanto, no necesita bibliotecas de terceros.C ++ 17 ahora tiene un
std::filesystem::directory_iterator
, que se puede usar comoAdemás, también
std::filesystem::recursive_directory_iterator
puede iterar los subdirectorios.fuente
namespace fs = std::experimental::filesystem;
. Aunque parece funcionar bien.std::filesystem::path
astd::cout
, las comillas se incluyen en la salida. Para evitar eso, agregue.string()
a la ruta para hacer una conversión explícita en lugar de implícita (aquístd::cout << p.string() << std::endl;
). Ejemplo: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3std::wstring
debería usarse o cuál es el tipo del iterador?-lstdc++fs
, obtendría unSIGSEGV (Address boundary error)
. No pude encontrar en ninguna parte de la documentación que esto fuera necesario, y el enlazador tampoco dio ninguna pista. Esto funcionó para ambosg++ 8.3.0
yclang 8.0.0-3
. ¿Alguien tiene alguna idea de dónde se especifica este tipo de cosas en los documentos / especificaciones?Desafortunadamente, el estándar C ++ no define una forma estándar de trabajar con archivos y carpetas de esta manera.
Dado que no existe una forma multiplataforma, la mejor forma multiplataforma es utilizar una biblioteca como el módulo de sistema de archivos boost .
Método de impulso multiplataforma:
Fuente de la página de impulso mencionada anteriormente.
Para sistemas basados en Unix / Linux:
Puede usar opendir / readdir / closedir .
Código fuente de las páginas de manual anteriores.
Para sistemas basados en Windows:
Puede utilizar las API de Win32 FindFirstFile / FindNextFile / FindClose funciones.
Código fuente de las páginas msdn anteriores.
fuente
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, con C ++ 17 existestd::filesystem
, que tiene una funcionalidad similar a boost (las libs se derivan de boost). Ver la respuesta de Shreevardhan a continuación.Una función es suficiente, no necesita usar ninguna biblioteca de terceros (para Windows).
PD: como mencionó @Sebastian, puede cambiar
*.*
a*.ext
para obtener solo los archivos EXT (es decir, de un tipo específico) en ese directorio.fuente
std::vector<std::wstring>
y luego enfileName.c_str()
lugar de un vector de cadenas, que no se compilaría.Para una solución única en C, por favor revise esto. Solo requiere un encabezado adicional:
https://github.com/cxong/tinydir
Algunas ventajas sobre otras opciones:
readdir_r
donde esté disponible, lo que significa que (generalmente) es seguro para subprocesosUNICODE
macrosfuente
Recomiendo usar
glob
con este envoltorio reutilizable. Genera una rutavector<string>
correspondiente al archivo que se ajusta al patrón global:Que luego se puede llamar con un patrón comodín del sistema normal como:
fuente
No such file or directory
. ¿Me puede decir cómo resolver este problema, por favor?GLOB_TILDE
conGLOB_TILDE | GLOB_MARK
y luego la comprobación de caminos que terminan en una barra. Tendrá que hacer cualquier modificación si lo necesita.glob
.Aquí hay un código muy simple al
C++11
usar laboost::filesystem
biblioteca para obtener nombres de archivos en un directorio (excluyendo los nombres de carpetas):La salida es como:
fuente
boost::filesystem
biblioteca boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm¿Por qué no usar
glob()
?fuente
Creo que el siguiente fragmento se puede usar para enumerar todos los archivos.
A continuación se muestra la estructura de la estructura dirent.
fuente
Prueba el método boost para x-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
o simplemente use su archivo de sistema operativo específico.
fuente
Echa un vistazo a esta clase que usa la API win32. Simplemente construya una instancia proporcionando el nombre
foldername
del cual desea el listado y luego llame algetNextFile
método para obtener el siguientefilename
del directorio. Creo que necesitawindows.h
ystdio.h
.fuente
GNU Manual FTW
http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister
Además, a veces es bueno ir directamente a la fuente (juego de palabras). Puedes aprender mucho mirando las entrañas de algunos de los comandos más comunes en Linux. He configurado un espejo simple de los coreutils de GNU en github (para leer).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Tal vez esto no aborde Windows, pero se pueden tener varios casos de uso de variantes de Unix utilizando estos métodos.
Espero que ayude...
fuente
La respuesta de Shreevardhan funciona muy bien. Pero si quieres usarlo en c ++ 14 solo haz un cambio
namespace fs = experimental::filesystem;
es decir,
fuente
fuente
Espero que este código te ayude.
fuente
string2wchar_t
devuelve la dirección de una variable local. Además, probablemente debería usar los métodos de conversión disponibles en WinAPI en lugar de escribir los suyos propios.Esta implementación cumple su propósito, llenando dinámicamente una serie de cadenas con el contenido del directorio especificado.
fuente
if
bloque. Lo llamo conchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Esto funciona para mi. Lo siento si no puedo recordar la fuente. Probablemente sea de una página de manual.
fuente
puede obtener todos los archivos directos en su directorio raíz utilizando std :: experimental :: filesystem :: directory_iterator (). Luego, lea el nombre de estos archivos de ruta.
fuente
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.
Descargue el archivo dirent.h de la página de github. Pero es mejor usar el archivo Raw dirent.h y seguir mis pasos a continuación (así es como lo hice funcionar).
Página de Github para dirent.h para Windows: página de Github para dirent.h
Archivo Dirent sin procesar: Archivo dirent.h sin procesar
Vaya a su proyecto y agregue un nuevo elemento ( Ctrl+ Shift+ A). Agregue un archivo de encabezado (.h) y asígnele el nombre dirent.h.
Pegue el código del archivo Raw dirent.h en su encabezado.
Incluya "dirent.h" en su código.
Ponga el siguiente
void filefinder()
método en su código y llámelo desde sumain
función o edite la función como quiera usarlo.fuente
El sistema lo llama!
Entonces solo lee el archivo.
EDITAR: esta respuesta debe considerarse un truco, pero realmente funciona (aunque sea de forma específica para la plataforma) si no tiene acceso a soluciones más elegantes.
fuente
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 utilizando funciones básicas de archivo en io.h. Puede reemplazar estas funciones en otra plataforma. Lo que quiero expresar es que la idea básica de DFS cumple perfectamente con este problema.
fuente
Traté de seguir el ejemplo dado en ambas respuestas y podría valer la pena señalar que parece que
std::filesystem::directory_entry
se ha cambiado para no tener una sobrecarga del<<
operador. En lugar destd::cout << p << std::endl;
tener que usar lo siguiente para poder compilar y hacer que funcione:tratando de pasar
p
por sí solo para dar comostd::cout <<
resultado un error de sobrecarga faltante.fuente
Sobre la base de lo que herohuyongtao publicó y algunas otras publicaciones:
http://www.cplusplus.com/forum/general/39766/
¿Cuál es el tipo de entrada esperado de FindFirstFile?
¿Cómo convertir wstring en cadena?
Esta es una solución de Windows.
Como quería pasar std :: string y devolver un vector de cadenas, tuve que hacer un par de conversiones.
fuente
WIN32_FIND_DATAA
,FindFirstFileA
yFindNextFileA
. Entonces no habrá necesidad de convertir el resultado a multibyte o la entrada a unicode.Es algo que quiero compartir y gracias por el material de lectura. Juega un poco con la función para entenderla. Te puede gustar. e representaba la extensión, p es para la ruta y s es para el separador de ruta.
Si la ruta se pasa sin terminar el separador, se agregará un separador a la ruta. Para la extensión, si se ingresa una cadena vacía, la función devolverá cualquier archivo que no tenga una extensión en su nombre. Si se ingresó una sola estrella, 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 hubiera contenido un punto en la posición cero.
Por un valor de retorno. 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 de retorno pero el tamaño del mapa es solo 1, eso significa que hubo un problema al abrir la ruta del directorio.
Tenga en cuenta que, para mayor eficiencia, esta 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á a qué función va a llamar en función de la entrada. ¿Por qué es eso más eficiente? Dijo que si va a capturar todo lo que es un archivo, al hacer ese método, la subfunción que se creó para capturar todos los archivos simplemente capturará todos los archivos y no necesita evaluar ninguna otra condición innecesaria cada vez que encuentra un archivo.
Eso también se aplicaría cuando tomas archivos que no tienen una extensión. Una función construida específica para ese propósito solo evaluaría el clima si el objeto encontrado es un archivo y luego si el nombre del archivo tiene un punto o no.
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.
fuente
fuente
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 por usted.
fuente