Comment puis-je déterminer la liste des fichiers dans un répertoire à partir de mon code C ou C ++?
Je ne suis pas autorisé à exécuter la ls
commande et à analyser les résultats à partir de mon programme.
Comment puis-je déterminer la liste des fichiers dans un répertoire à partir de mon code C ou C ++?
Je ne suis pas autorisé à exécuter la ls
commande et à analyser les résultats à partir de mon programme.
Réponses:
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:
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
std::string path = "/path/to/directory";
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
}
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.
C ++ 17 a maintenant un std::filesystem::directory_iterator
, qui peut être utilisé comme
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
std::string path = "/path/to/directory";
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
}
En outre, std::filesystem::recursive_directory_iterator
peut itérer les sous - répertoires aussi bien.
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 (ici std::cout << p.string() << std::endl;
). Exemple: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
std::wstring
être utilisé ou quel est le type de l'itérateur?
-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.0
et 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?
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)) 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; }
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 .
Un exemple de code qui recherche dans un répertoire l'entrée `` nom '' est:
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;
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 .
L'exemple C ++ suivant vous montre une utilisation minimale 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); } }
Code source des pages msdn ci-dessus.
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
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 *.*
à *.ext
afin d'obtenir uniquement les fichiers EXT (c'est-à-dire d'un type spécifique) dans ce répertoire.
std::vector<std::wstring>
et puis fileName.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
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);
Quelques avantages par rapport aux autres options:
readdir_r
lorsqu'il est disponible, ce qui signifie qu'il est (généralement) threadsafeUNICODE
macrosJe recommande d'utiliser glob
avec cet emballage réutilisable. Il génère un vector<string>
chemin de fichier correspondant au modèle de 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;
}
Qui peut ensuite être appelé avec un modèle générique de système normal tel que:
vector<string> files = globVector("./*");
No such file or directory
. Pouvez-vous me dire comment résoudre ce problème s'il vous plaît?
GLOB_TILDE
avec GLOB_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 la boost::filesystem
bibliothè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>
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 sortie est comme:
file1.txt
file2.dat
boost::filesystem
bibliothèque boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm
Pourquoi ne pas utiliser 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;
}
Je pense que l'extrait ci-dessous peut être utilisé pour répertorier tous les fichiers.
#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);
}
Voici la structure de la structure 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 */
};
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.
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 la getNextFile
méthode pour obtenir la suivante à filename
partir du répertoire. Je pense qu'il a besoin windows.h
et 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;
}
};
GNU Manual FTW
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 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>
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;
}
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;
}
J'espère que ce code vous aidera.
#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;
}
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é.
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;
}
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.
#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/");
}
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.
#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;
}
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 votre main
fonction 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 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);
}
Appelez-le!
system( "dir /b /s /a-d * > file_names.txt" );
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.
É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>
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);
}
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:
#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;
}
essayer de passer p
par lui-même pour std::cout <<
entraîner une erreur de surcharge manquante.
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.
#include <string>
#include <Windows.h>
#include <vector>
#include <locale>
#include <codecvt>
std::vector<std::string> listFilesInDir(std::string path)
{
std::vector<std::string> names;
//Convert string to wstring
std::wstring search_path = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(path);
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))
{
//convert from wide char to narrow char array
char ch[260];
char DefChar = ' ';
WideCharToMultiByte(CP_ACP, 0, fd.cFileName, -1, ch, 260, &DefChar, NULL);
names.push_back(ch);
}
}
while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
WIN32_FIND_DATAA
, FindFirstFileA
et FindNextFileA
. 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.
#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;
}
#include<iostream>
#include <dirent.h>
using namespace std;
char ROOT[]={'.'};
void listfiles(char* path){
DIR * dirp = opendir(path);
dirent * dp;
while ( (dp = readdir(dirp)) !=NULL ) {
cout << dp->d_name << " size " << dp->d_reclen<<std::endl;
}
(void)closedir(dirp);
}
int main(int argc, char **argv)
{
char* path;
if (argc>1) path=argv[1]; else path=ROOT;
cout<<"list files in ["<<path<<"]"<<std::endl;
listfiles(path);
return 0;
}
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.
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;
}
}