@chrish - Oui mais celui-ci a le classique "Je n'ai pas le droit d'exécuter le 'l'"! C'est exactement ce que je ressentirais en 1ère année d'informatique. ; D <3 x
James Bedford
1
C et C ++ ne sont pas le même langage. Par conséquent, la procédure pour accomplir cette tâche sera différente dans les deux langues. Veuillez en choisir un et réétiqueter en conséquence.
MD XF
2
Et aucun de ces langages (autre que C ++ depuis C ++ 17) n'a même un concept de répertoire - donc toute réponse dépendra probablement de votre système d'exploitation, ou des bibliothèques d'abstraction que vous pourriez utiliser.
Toby Speight
Réponses:
810
Dans les petites et simples tâches, je n'utilise pas boost, j'utilise dirent.h qui est également disponible pour 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;}
C'est juste un petit fichier d'en-tête et fait la plupart des choses simples dont vous avez besoin sans utiliser une grande approche basée sur des modèles comme boost (sans offense, j'aime boost!).
L'auteur de la couche de compatibilité Windows est Toni Ronkko. Sous Unix, c'est un en-tête standard.
MISE À JOUR 2017 :
En C ++ 17 il y a maintenant un moyen officiel de la liste des fichiers de votre système de fichiers: std::filesystem. Il y a une excellente réponse de Shreevardhan ci-dessous avec ce code source:
@ArtOfWarfare: tinydir n'a même pas été créé lors de la réponse à cette question. C'est aussi un wrapper autour de dirent (POSIX) et FindFirstFile (Windows), tandis que dirent.h enveloppe simplement dirent pour Windows. Je pense que c'est un goût personnel, mais dirent.h se sent plus comme un standard
Peter Parker
7
@JoshC: parce que * ent est juste un pointeur renvoyé de la représentation interne. en fermant le répertoire, vous éliminerez également le * ent. Comme le * ent est uniquement pour la lecture, c'est une conception saine, je pense.
Peter Parker
42
les gens deviennent réels !! c'est une question de 2009 et elle n'a même pas mentionné VS. Donc, ne critiquez pas que votre IDE propriétaire (bien que très agréable) ne supporte pas les normes de système d'exploitation séculaires. Aussi ma réponse a dit qu'il est "disponible" pour Windows, pas "inclus" dans n'importe quel IDE à partir de maintenant et pour toujours ... Je suis sûr que vous pouvez télécharger dirent et le mettre dans certains include dir et le tour est joué.
Peter Parker
6
La réponse est trompeuse. Il doit commencer par: " ... J'utilise dirent.h , pour lequel une couche de compatibilité open-source Windows existe également ".
rustyx
10
Avec C ++ 14 il y en a std::experimental::filesystem, avec C ++ 17 il y en a std::filesystem. Voir la réponse de Shreevardhan ci-dessous. Donc pas besoin de bibliothèques tierces.
AFAIK peut également être utilisé en C ++ 14, mais il est encore au stade expérimental: namespace fs = std::experimental::filesystem;. Il semble que ça marche bien.
PeterK
7
Cela devrait être la réponse préférée pour une utilisation actuelle (à partir de C ++ 17)
diode verte
4
Faites attention lors du passage std::filesystem::pathà std::cout, les guillemets sont inclus dans la sortie. Pour éviter cela, ajoutez .string()au chemin pour effectuer une conversion explicite au lieu d'une conversion implicite (ici std::cout << p.string() << std::endl;). Exemple: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
Roi Danton
2
Qu'en est-il des caractères NON ASCII dans les noms de fichiers? Ne devrait pas std::wstringêtre utilisé ou quel est le type de l'itérateur?
anddero
2
Je ne sais pas si je suis seul dans ce domaine, mais sans lien avec -lstdc++fs, j'aurais un SIGSEGV (Address boundary error). Je n'ai trouvé nulle part dans la documentation que cela était nécessaire, et l'éditeur de liens n'a donné aucun indice non plus. Cela a fonctionné pour les deux g++ 8.3.0et clang 8.0.0-3. Quelqu'un at-il une idée de l'endroit où des choses comme celle-ci sont spécifiées dans les documents / spécifications?
swalog
229
Malheureusement, la norme C ++ ne définit pas une manière standard de travailler avec des fichiers et des dossiers de cette manière.
Puisqu'il n'y a pas de moyen multiplateforme, le meilleur moyen multiplateforme est d'utiliser une bibliothèque telle que le module boost de système de fichiers .
Méthode de multiplication multiplateforme:
La fonction suivante, étant donné un chemin de répertoire et un nom de fichier, recherche récursivement dans le répertoire et ses sous-répertoires le nom de fichier, en renvoyant un booléen et, en cas de succès, le chemin d'accès au fichier trouvé.
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;}
Source à partir de la page boost mentionnée ci-dessus.
Avec C ++ 14, il existe std::experimental::filesystem, avec C ++ 17 std::filesystem, qui ont des fonctionnalités similaires à boost (les bibliothèques sont dérivées de boost). Voir la réponse de Shreevardhan ci-dessous.
Une fonction suffit, vous n'avez pas besoin d'utiliser de bibliothèque tierce (pour 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;}
PS: comme mentionné par @Sebastian, vous pouvez passer *.*à *.extafin d'obtenir uniquement les fichiers EXT (c'est-à-dire d'un type spécifique) dans ce répertoire.
Cette solution est spécifique à la plate-forme. C'est la raison pour laquelle vous avez besoin de bibliothèques tierces.
kraxor
9
@kraxor Oui, cela ne fonctionne que sous Windows, mais OP ne demande jamais d'avoir une solution multiplateforme. BTW, je préfère toujours choisir quelque chose sans utiliser de 3e bibliothèques (si possible).
herohuyongtao
7
@herohuyongtao OP n'a jamais spécifié de plateforme, et donner une solution fortement dépendante de la plateforme à une question générique peut être trompeur. (Et s'il y a une solution à une ligne qui ne fonctionne que sur PlayStation 3? Est-ce une bonne réponse ici?) Je vois que vous avez modifié votre réponse pour indiquer qu'elle ne fonctionne que sur Windows, je suppose que c'est bien comme ça.
kraxor
1
@herohuyongtao OP a mentionné qu'il ne peut pas analyser ls, ce qui signifie qu'il est probablement sous unix .. de toute façon, bonne réponse pour Windows.
Thomas
2
J'ai fini par utiliser un std::vector<std::wstring>et puis fileName.c_str()au lieu d'un vecteur de chaînes, qui ne compilerait pas.
PerryC
51
Pour une solution C uniquement, veuillez vérifier ceci. Il ne nécessite qu'un en-tête supplémentaire:
Très belle suggestion. Je ne l'ai pas encore testé sur un ordinateur Windows mais il fonctionne à
merveille
La bibliothèque ne prend pas en charge std :: string, vous ne pouvez donc pas passer file.c_str () à tinydir_open. Dans ce cas, il donne l'erreur C2664 lors de la compilation sur msvc 2015.
Stepan Yakovenko
33
Je recommande d'utiliser globavec cet emballage réutilisable. Il génère un vector<string>chemin de fichier correspondant au modèle de glob:
Je voudrais utiliser glob.h comme vous l'avez recommandé. Mais quand même, je ne peux pas inclure le fichier .h: ça dit No such file or directory. Pouvez-vous me dire comment résoudre ce problème s'il vous plaît?
Tofuw
Notez que cette routine ne va que d'un niveau (pas de récursivité). Il ne fait pas non plus de vérification rapide pour déterminer s'il s'agit d'un fichier ou d'un répertoire, ce que vous pouvez faire facilement en basculant GLOB_TILDEavec GLOB_TILDE | GLOB_MARKpuis en vérifiant les chemins se terminant par une barre oblique. Vous devrez y apporter une modification si vous en avez besoin.
Volomike
Cette plate-forme est-elle compatible?
Nikhil Augustine
Malheureusement, vous ne pouvez pas trouver de fichiers uniformément cachés via glob.
LmTinyToon
23
Voici un code très simple pour C++11utiliser la boost::filesystembibliothèque pour obtenir les noms de fichiers dans un répertoire (à l'exclusion des noms de dossier):
#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;}}
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 */};
Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien de référence. Les réponses de lien uniquement peuvent devenir invalides si la page liée change. - De l'avis
ice1000
@ ice1000 Sérieusement? Ce Q & A est de 2009
Tim
8
Découvrez cette classe qui utilise l'API Win32. Construisez simplement une instance en fournissant la liste à foldernamepartir de laquelle vous souhaitez la liste, puis appelez la getNextFileméthode pour obtenir la suivante à filenamepartir du répertoire. Je pense qu'il a besoin windows.het 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;}};
De plus, il est parfois bon d'aller directement à la source (jeu de mots voulu). Vous pouvez en apprendre beaucoup en examinant les entrailles de certaines des commandes les plus courantes de Linux. J'ai mis en place un simple miroir des coreutils de GNU sur github (pour la lecture).
Peut-être que cela ne concerne pas Windows, mais un certain nombre de cas d'utilisation de variantes Unix peuvent être rencontrés en utilisant ces méthodes.
La réponse de Shreevardhan fonctionne très bien. Mais si vous voulez l'utiliser en c ++ 14, faites un changementnamespace fs = experimental::filesystem;
c'est à dire,
#include<string>#include<iostream>#include<filesystem>usingnamespace 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;}
-1. string2wchar_trenvoie l'adresse d'une variable locale. De plus, vous devriez probablement utiliser les méthodes de conversion disponibles dans WinAPI au lieu d'écrire les vôtres.
Daniel Kamil Kozar
3
Cette implémentation réalise votre objectif, remplissant dynamiquement un tableau de chaînes avec le contenu du répertoire spécifié.
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;}
Comment pourrais-je appeler cela? Je reçois des erreurs de segmentation lorsque j'essaie d'exécuter cette fonction sur le premier ifbloc. Je l'appelle avecchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Hal T
2
Cela fonctionne pour moi. Je suis désolé si je ne me souviens pas de la source. Il s'agit probablement d'une page de manuel.
vous pouvez obtenir tous les fichiers directement dans votre répertoire racine en utilisant std :: experimental :: filesystem :: directory_iterator (). Ensuite, lisez le nom de ces fichiers de chemins.
Cette réponse devrait fonctionner pour les utilisateurs de Windows qui ont eu du mal à le faire fonctionner avec Visual Studio avec l'une des autres réponses.
Téléchargez le fichier dirent.h depuis la page github. Mais il vaut mieux simplement utiliser le fichier Raw dirent.h et suivre mes étapes ci-dessous (c'est ainsi que je l'ai fait fonctionner).
Mettez la void filefinder()méthode ci-dessous dans votre code et appelez-la depuis votre mainfonction ou modifiez la fonction comme vous voulez l'utiliser.
#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);}
EDIT: Cette réponse doit être considérée comme un hack, mais elle fonctionne vraiment (bien que d'une manière spécifique à la plate-forme) si vous n'avez pas accès à des solutions plus élégantes.
Je ne suis pas autorisé à exécuter la commande «ls» et à analyser les résultats à partir de mon programme. Je savais qu'il y aurait quelqu'un qui enverrait quelque chose comme ça ...
yyny
1
Étant donné que les fichiers et les sous-répertoires d'un répertoire sont généralement stockés dans une arborescence, une méthode intuitive consiste à utiliser l'algorithme DFS pour parcourir récursivement chacun d'eux. Voici un exemple dans le système d'exploitation Windows en utilisant les fonctions de base des fichiers dans io.h. Vous pouvez remplacer ces fonctions dans une autre plate-forme. Ce que je veux exprimer, c'est que l'idée de base de DFS répond parfaitement à ce problème.
#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);}
J'ai essayé de suivre l'exemple donné dans les deux réponses et il pourrait être intéressant de noter qu'il semble std::filesystem::directory_entryavoir été modifié pour ne pas avoir de surcharge de l' <<opérateur. Au lieu de cela, std::cout << p << std::endl;j'ai dû utiliser ce qui suit pour pouvoir compiler et le faire fonctionner:
Si vous savez que vous n'utiliserez que plusieurs octets, vous pourriez utiliser WIN32_FIND_DATAA, FindFirstFileAet FindNextFileA. Ensuite, il ne sera pas nécessaire de convertir le résultat en plusieurs octets ou l'entrée en unicode.
Kiran Thilak
0
Juste quelque chose que je veux partager et merci pour le matériel de lecture. Jouez avec la fonction un peu pour la comprendre. Vous l'aimerez peut-être. e signifie extension, p est pour chemin et s est pour séparateur de chemin.
Si le chemin est passé sans terminer le séparateur, un séparateur sera ajouté au chemin. Pour l'extension, si une chaîne vide est entrée, la fonction renverra tout fichier qui n'a pas d'extension dans son nom. Si une seule étoile a été entrée, tous les fichiers du répertoire seront retournés. Si la longueur e est supérieure à 0 mais n'est pas un simple *, un point sera ajouté à e si e n'avait pas contenu de point à la position zéro.
Pour une valeur de retour. Si une carte de longueur nulle est renvoyée, rien n'a été trouvé mais le répertoire était bien ouvert. Si l'index 999 est disponible à partir de la valeur de retour mais que la taille de la carte n'est que de 1, cela signifie qu'il y a eu un problème avec l'ouverture du chemin du répertoire.
Notez que pour plus d'efficacité, cette fonction peut être divisée en 3 fonctions plus petites. En plus de cela, vous pouvez créer une fonction d'appelant qui détectera la fonction qu'il va appeler en fonction de l'entrée. Pourquoi est-ce plus efficace? Dit que si vous allez récupérer tout ce qui est un fichier, en utilisant cette méthode, la sous-fonction qui a été conçue pour récupérer tous les fichiers ne fera que récupérer tous les fichiers et n'a pas besoin d'évaluer toute autre condition inutile à chaque fois qu'il trouve un fichier.
Cela s'appliquerait également lorsque vous récupérez des fichiers sans extension. Une fonction spécifique construite à cet effet n'évaluerait la météo que si l'objet trouvé est un fichier et si le nom du fichier contient ou non un point.
L'économie peut ne pas être importante si vous ne lisez que les répertoires contenant moins de fichiers. Mais si vous lisez une grande quantité de répertoire ou si le répertoire contient quelques centaines de milliers de fichiers, cela pourrait être une énorme économie.
#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;}
Cela a fonctionné pour moi. Il écrit un fichier avec juste les noms (pas de chemin) de tous les fichiers. Ensuite, il lit ce fichier txt et l'imprime pour vous.
stat()
erreur «aucun fichier ou répertoire» lorsque le nom de fichier est renvoyé parreaddir()
.Réponses:
Dans les petites et simples tâches, je n'utilise pas boost, j'utilise dirent.h qui est également disponible pour Windows:
C'est juste un petit fichier d'en-tête et fait la plupart des choses simples dont vous avez besoin sans utiliser une grande approche basée sur des modèles comme boost (sans offense, j'aime boost!).
L'auteur de la couche de compatibilité Windows est Toni Ronkko. Sous Unix, c'est un en-tête standard.
MISE À JOUR 2017 :
En C ++ 17 il y a maintenant un moyen officiel de la liste des fichiers de votre système de fichiers:
std::filesystem
. Il y a une excellente réponse de Shreevardhan ci-dessous avec ce code source:la source
std::experimental::filesystem
, avec C ++ 17 il y en astd::filesystem
. Voir la réponse de Shreevardhan ci-dessous. Donc pas besoin de bibliothèques tierces.C ++ 17 a maintenant un
std::filesystem::directory_iterator
, qui peut être utilisé commeEn outre,
std::filesystem::recursive_directory_iterator
peut itérer les sous - répertoires aussi bien.la source
namespace fs = std::experimental::filesystem;
. Il semble que ça marche bien.std::filesystem::path
àstd::cout
, les guillemets sont inclus dans la sortie. Pour éviter cela, ajoutez.string()
au chemin pour effectuer une conversion explicite au lieu d'une conversion implicite (icistd::cout << p.string() << std::endl;
). Exemple: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3std::wstring
être utilisé ou quel est le type de l'itérateur?-lstdc++fs
, j'aurais unSIGSEGV (Address boundary error)
. Je n'ai trouvé nulle part dans la documentation que cela était nécessaire, et l'éditeur de liens n'a donné aucun indice non plus. Cela a fonctionné pour les deuxg++ 8.3.0
etclang 8.0.0-3
. Quelqu'un at-il une idée de l'endroit où des choses comme celle-ci sont spécifiées dans les documents / spécifications?Malheureusement, la norme C ++ ne définit pas une manière standard de travailler avec des fichiers et des dossiers de cette manière.
Puisqu'il n'y a pas de moyen multiplateforme, le meilleur moyen multiplateforme est d'utiliser une bibliothèque telle que le module boost de système de fichiers .
Méthode de multiplication multiplateforme:
Source à partir de la page boost mentionnée ci-dessus.
Pour les systèmes basés sur Unix / Linux:
Vous pouvez utiliser opendir / readdir / closedir .
Code source des pages de manuel ci-dessus.
Pour les systèmes basés sur Windows:
Vous pouvez utiliser les fonctions FindFirstFile / FindNextFile / FindClose de l' API Win32 .
Code source des pages msdn ci-dessus.
la source
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, avec C ++ 17std::filesystem
, qui ont des fonctionnalités similaires à boost (les bibliothèques sont dérivées de boost). Voir la réponse de Shreevardhan ci-dessous.Une fonction suffit, vous n'avez pas besoin d'utiliser de bibliothèque tierce (pour Windows).
PS: comme mentionné par @Sebastian, vous pouvez passer
*.*
à*.ext
afin d'obtenir uniquement les fichiers EXT (c'est-à-dire d'un type spécifique) dans ce répertoire.la source
std::vector<std::wstring>
et puisfileName.c_str()
au lieu d'un vecteur de chaînes, qui ne compilerait pas.Pour une solution C uniquement, veuillez vérifier ceci. Il ne nécessite qu'un en-tête supplémentaire:
https://github.com/cxong/tinydir
Quelques avantages par rapport aux autres options:
readdir_r
lorsqu'il est disponible, ce qui signifie qu'il est (généralement) threadsafeUNICODE
macrosla source
Je recommande d'utiliser
glob
avec cet emballage réutilisable. Il génère unvector<string>
chemin de fichier correspondant au modèle de glob:Qui peut ensuite être appelé avec un modèle générique de système normal tel que:
la source
No such file or directory
. Pouvez-vous me dire comment résoudre ce problème s'il vous plaît?GLOB_TILDE
avecGLOB_TILDE | GLOB_MARK
puis en vérifiant les chemins se terminant par une barre oblique. Vous devrez y apporter une modification si vous en avez besoin.glob
.Voici un code très simple pour
C++11
utiliser laboost::filesystem
bibliothèque pour obtenir les noms de fichiers dans un répertoire (à l'exclusion des noms de dossier):La sortie est comme:
la source
boost::filesystem
bibliothèque boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htmPourquoi ne pas utiliser
glob()
?la source
Je pense que l'extrait ci-dessous peut être utilisé pour répertorier tous les fichiers.
Voici la structure de la structure dirent
la source
Essayez la méthode boost pour x-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
ou utilisez simplement votre fichier spécifique au système d'exploitation.
la source
Découvrez cette classe qui utilise l'API Win32. Construisez simplement une instance en fournissant la liste à
foldername
partir de laquelle vous souhaitez la liste, puis appelez lagetNextFile
méthode pour obtenir la suivante àfilename
partir du répertoire. Je pense qu'il a besoinwindows.h
etstdio.h
.la source
GNU Manual FTW
http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister
De plus, il est parfois bon d'aller directement à la source (jeu de mots voulu). Vous pouvez en apprendre beaucoup en examinant les entrailles de certaines des commandes les plus courantes de Linux. J'ai mis en place un simple miroir des coreutils de GNU sur github (pour la lecture).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Peut-être que cela ne concerne pas Windows, mais un certain nombre de cas d'utilisation de variantes Unix peuvent être rencontrés en utilisant ces méthodes.
J'espère que cela pourra aider...
la source
La réponse de Shreevardhan fonctionne très bien. Mais si vous voulez l'utiliser en c ++ 14, faites un changement
namespace fs = experimental::filesystem;
c'est à dire,
la source
la source
J'espère que ce code vous aidera.
la source
string2wchar_t
renvoie l'adresse d'une variable locale. De plus, vous devriez probablement utiliser les méthodes de conversion disponibles dans WinAPI au lieu d'écrire les vôtres.Cette implémentation réalise votre objectif, remplissant dynamiquement un tableau de chaînes avec le contenu du répertoire spécifié.
la source
if
bloc. Je l'appelle avecchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Cela fonctionne pour moi. Je suis désolé si je ne me souviens pas de la source. Il s'agit probablement d'une page de manuel.
la source
vous pouvez obtenir tous les fichiers directement dans votre répertoire racine en utilisant std :: experimental :: filesystem :: directory_iterator (). Ensuite, lisez le nom de ces fichiers de chemins.
la source
Cette réponse devrait fonctionner pour les utilisateurs de Windows qui ont eu du mal à le faire fonctionner avec Visual Studio avec l'une des autres réponses.
Téléchargez le fichier dirent.h depuis la page github. Mais il vaut mieux simplement utiliser le fichier Raw dirent.h et suivre mes étapes ci-dessous (c'est ainsi que je l'ai fait fonctionner).
Page Github pour dirent.h pour Windows: Page Github pour dirent.h
Fichier Dirent brut: fichier dirent.h brut
Accédez à votre projet et ajoutez un nouvel élément ( Ctrl+ Shift+ A). Ajoutez un fichier d'en-tête (.h) et nommez-le dirent.h.
Collez le code Raw dirent.h File dans votre en-tête.
Incluez "dirent.h" dans votre code.
Mettez la
void filefinder()
méthode ci-dessous dans votre code et appelez-la depuis votremain
fonction ou modifiez la fonction comme vous voulez l'utiliser.la source
Appelez-le!
Ensuite, lisez simplement le fichier.
EDIT: Cette réponse doit être considérée comme un hack, mais elle fonctionne vraiment (bien que d'une manière spécifique à la plate-forme) si vous n'avez pas accès à des solutions plus élégantes.
la source
Étant donné que les fichiers et les sous-répertoires d'un répertoire sont généralement stockés dans une arborescence, une méthode intuitive consiste à utiliser l'algorithme DFS pour parcourir récursivement chacun d'eux. Voici un exemple dans le système d'exploitation Windows en utilisant les fonctions de base des fichiers dans io.h. Vous pouvez remplacer ces fonctions dans une autre plate-forme. Ce que je veux exprimer, c'est que l'idée de base de DFS répond parfaitement à ce problème.
la source
J'ai essayé de suivre l'exemple donné dans les deux réponses et il pourrait être intéressant de noter qu'il semble
std::filesystem::directory_entry
avoir été modifié pour ne pas avoir de surcharge de l'<<
opérateur. Au lieu de cela,std::cout << p << std::endl;
j'ai dû utiliser ce qui suit pour pouvoir compiler et le faire fonctionner:essayer de passer
p
par lui-même pourstd::cout <<
entraîner une erreur de surcharge manquante.la source
S'appuyant sur ce que herohuyongtao a publié et quelques autres messages:
http://www.cplusplus.com/forum/general/39766/
Quel est le type d'entrée attendu de FindFirstFile?
Comment convertir wstring en chaîne?
Ceci est une solution Windows.
Puisque je voulais passer dans std :: string et retourner un vecteur de chaînes, j'ai dû faire quelques conversions.
la source
WIN32_FIND_DATAA
,FindFirstFileA
etFindNextFileA
. Ensuite, il ne sera pas nécessaire de convertir le résultat en plusieurs octets ou l'entrée en unicode.Juste quelque chose que je veux partager et merci pour le matériel de lecture. Jouez avec la fonction un peu pour la comprendre. Vous l'aimerez peut-être. e signifie extension, p est pour chemin et s est pour séparateur de chemin.
Si le chemin est passé sans terminer le séparateur, un séparateur sera ajouté au chemin. Pour l'extension, si une chaîne vide est entrée, la fonction renverra tout fichier qui n'a pas d'extension dans son nom. Si une seule étoile a été entrée, tous les fichiers du répertoire seront retournés. Si la longueur e est supérieure à 0 mais n'est pas un simple *, un point sera ajouté à e si e n'avait pas contenu de point à la position zéro.
Pour une valeur de retour. Si une carte de longueur nulle est renvoyée, rien n'a été trouvé mais le répertoire était bien ouvert. Si l'index 999 est disponible à partir de la valeur de retour mais que la taille de la carte n'est que de 1, cela signifie qu'il y a eu un problème avec l'ouverture du chemin du répertoire.
Notez que pour plus d'efficacité, cette fonction peut être divisée en 3 fonctions plus petites. En plus de cela, vous pouvez créer une fonction d'appelant qui détectera la fonction qu'il va appeler en fonction de l'entrée. Pourquoi est-ce plus efficace? Dit que si vous allez récupérer tout ce qui est un fichier, en utilisant cette méthode, la sous-fonction qui a été conçue pour récupérer tous les fichiers ne fera que récupérer tous les fichiers et n'a pas besoin d'évaluer toute autre condition inutile à chaque fois qu'il trouve un fichier.
Cela s'appliquerait également lorsque vous récupérez des fichiers sans extension. Une fonction spécifique construite à cet effet n'évaluerait la météo que si l'objet trouvé est un fichier et si le nom du fichier contient ou non un point.
L'économie peut ne pas être importante si vous ne lisez que les répertoires contenant moins de fichiers. Mais si vous lisez une grande quantité de répertoire ou si le répertoire contient quelques centaines de milliers de fichiers, cela pourrait être une énorme économie.
la source
la source
Cela a fonctionné pour moi. Il écrit un fichier avec juste les noms (pas de chemin) de tous les fichiers. Ensuite, il lit ce fichier txt et l'imprime pour vous.
la source