Jak mogę ustalić listę plików w katalogu z mojego kodu C lub C ++?
Nie wolno mi wykonywać ls
polecenia i analizować wyników z poziomu mojego programu.
Jak mogę ustalić listę plików w katalogu z mojego kodu C lub C ++?
Nie wolno mi wykonywać ls
polecenia i analizować wyników z poziomu mojego programu.
Odpowiedzi:
W małych i prostych zadaniach nie używam doładowania, używam dirent.h, który jest również dostępny dla systemu 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;
}
Jest to tylko mały plik nagłówkowy i wykonuje większość prostych czynności, których potrzebujesz, bez korzystania z dużego podejścia opartego na szablonie, takiego jak boost (bez obrazy, lubię boost!).
Autorem warstwy zgodności z systemem Windows jest Toni Ronkko. W Uniksie jest to standardowy nagłówek.
AKTUALIZACJA 2017 :
W C ++ 17 jest teraz oficjalnym sposób do plików wykazu systemu plików: std::filesystem
. Poniżej znajduje się doskonała odpowiedź Shreevardhan z tego kodu źródłowego:
#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
, w C ++ 17 jest std::filesystem
. Zobacz odpowiedź Shreevardhan poniżej. Więc nie ma potrzeby bibliotek zewnętrznych.
C ++ 17 ma teraz std::filesystem::directory_iterator
, którego można używać jako
#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;
}
Ponadto, std::filesystem::recursive_directory_iterator
można iteracyjne podkatalogi również.
namespace fs = std::experimental::filesystem;
. Wygląda na to, że działa dobrze.
std::filesystem::path
do std::cout
cudzysłowu są uwzględniane w danych wyjściowych. Aby tego uniknąć, dołącz .string()
do ścieżki, aby wykonać jawną zamiast niejawnej konwersji (tutaj std::cout << p.string() << std::endl;
). Przykład: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
std::wstring
należy używać lub jaki jest typ z iteratora?
-lstdc++fs
, dostałbym SIGSEGV (Address boundary error)
. Nigdzie w dokumentacji nie mogłem znaleźć, że jest to wymagane, a linker nie dał mi żadnej wskazówki. To działało zarówno dla, jak g++ 8.3.0
i dla clang 8.0.0-3
. Czy ktoś ma jakiś wgląd w to, gdzie takie rzeczy są określone w dokumentach / specyfikacjach?
Niestety standard C ++ nie definiuje standardowego sposobu pracy z plikami i folderami w ten sposób.
Ponieważ nie ma metody wieloplatformowej, najlepszym sposobem wieloplatformowym jest użycie biblioteki, takiej jak moduł systemu plików doładowania .
Metoda doładowania między platformami:
Poniższa funkcja, podając ścieżkę do katalogu i nazwę pliku, rekursywnie przeszukuje katalog i jego podkatalogi w poszukiwaniu nazwy pliku, zwracając wartość bool i, jeśli się powiedzie, ścieżkę do znalezionego pliku.
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; }
Źródło ze strony doładowania wspomnianej powyżej.
W systemach opartych na Unix / Linux:
Możesz użyć opendir / readdir / closedir .
Przykładowy kod przeszukujący katalog pod kątem wpisu `` nazwa '' to:
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;
Kod źródłowy z powyższych stron podręcznika.
W przypadku systemów opartych na systemie Windows:
Możesz użyć funkcji Win32 API FindFirstFile / FindNextFile / FindClose .
Poniższy przykład C ++ pokazuje minimalne użycie 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); } }
Kod źródłowy z powyższych stron msdn.
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, w C ++ 17 istnieje std::filesystem
, który ma podobną funkcjonalność jak boost (biblioteki lib pochodzą z boost). Zobacz odpowiedź Shreevardhan poniżej.
Wystarczy jedna funkcja, nie musisz używać żadnej biblioteki innej firmy (dla systemu 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: jak wspomniano w @Sebastian, możesz zmienić *.*
na *.ext
, aby uzyskać tylko pliki EXT (tj. Określonego typu) w tym katalogu.
std::vector<std::wstring>
a następnie fileName.c_str()
zamiast wektora ciągów, których nie można skompilować.
Sprawdź tylko rozwiązanie typu C. Wymaga tylko dodatkowego nagłówka:
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);
Niektóre zalety w stosunku do innych opcji:
readdir_r
tam, gdzie jest dostępny, co oznacza, że jest (zwykle) bezpieczny dla wątkówUNICODE
makrPolecam używać glob
z tym opakowaniem wielokrotnego użytku. Generuje vector<string>
odpowiadające ścieżki plików, które pasują do wzorca globu:
#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;
}
Które można następnie wywołać za pomocą normalnego systemu symboli wieloznacznych, takiego jak:
vector<string> files = globVector("./*");
No such file or directory
. Czy możesz mi powiedzieć, jak rozwiązać ten problem?
GLOB_TILDE
się, GLOB_TILDE | GLOB_MARK
a następnie sprawdzając ścieżki kończące się ukośnikiem. W razie potrzeby musisz wprowadzić dowolną modyfikację.
glob
.
Oto bardzo prosty kod przy C++11
użyciu boost::filesystem
biblioteki do uzyskiwania nazw plików w katalogu (z wyjątkiem nazw folderów):
#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;
}
}
Wyjście jest jak:
file1.txt
file2.dat
boost::filesystem
biblioteki boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm
Dlaczego nie użyć 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;
}
Myślę, że poniżej fragmentu można użyć do wyświetlenia wszystkich plików.
#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);
}
Poniżej znajduje się struktura struktury 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 */
};
Wypróbuj boost dla metody X-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
lub po prostu użyj plików specyficznych dla systemu operacyjnego.
Sprawdź tę klasę, która korzysta z interfejsu API win32. Wystarczy skonstruować instancję, podając foldername
żądaną pozycję, a następnie wywołać getNextFile
metodę, aby uzyskać następną filename
z katalogu. Myślę, że potrzebuje windows.h
i 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;
}
};
Podręcznik GNU FTW
Czasami dobrze jest przejść od razu do źródła (zamierzona gra słów). Możesz się wiele nauczyć, patrząc na niektóre z najczęściej używanych poleceń w Linuksie. Założyłem proste zwierciadło podstawowych plików GNU na github (do czytania).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Być może nie dotyczy to systemu Windows, ale przy użyciu tych metod można mieć wiele przypadków użycia wariantów uniksowych.
Mam nadzieję, że pomoże ...
Odpowiedź Shreevardhan działa świetnie. Ale jeśli chcesz go użyć w c ++ 14, po prostu dokonaj zmianynamespace fs = experimental::filesystem;
to znaczy,
#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;
}
Mam nadzieję, że ten kod ci pomoże.
#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
zwraca adres zmiennej lokalnej. Powinieneś także prawdopodobnie użyć metod konwersji dostępnych w WinAPI zamiast pisać własne.
Ta implementacja realizuje Twój cel, dynamicznie wypełniając tablicę ciągów treścią określonego katalogu.
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
bloku. Nazywam to zchar **list; int numItems; exploreDirectory("/folder",list, numItems);
To działa dla mnie. Przepraszam, jeśli nie pamiętam źródła. Prawdopodobnie pochodzi ze strony podręcznika man.
#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/");
}
możesz pobrać wszystkie bezpośrednie pliki z katalogu głównego, używając std :: experimental :: filesystem :: directory_iterator (). Następnie przeczytaj nazwę tych ścieżek.
#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;
}
Ta odpowiedź powinna działać dla użytkowników systemu Windows, którzy mieli problemy z uzyskaniem pracy z Visual Studio z innymi odpowiedziami.
Pobierz plik dirent.h ze strony github. Ale lepiej jest po prostu użyć pliku Raw dirent.h i postępować zgodnie z poniższymi krokami (tak mam go uruchomić).
Strona Github dla dirent.h dla Windows: Strona Github dla dirent.h
Plik Raw Dirent : Plik Raw dirent.h
Przejdź do swojego projektu i dodaj nowy przedmiot ( Ctrl+ Shift+ A). Dodaj plik nagłówka (.h) i nazwij go dirent.h.
Wklej kod pliku Raw dirent.h do nagłówka.
Dołącz „dirent.h” do swojego kodu.
Umieść poniższą void filefinder()
metodę w swoim kodzie i wywołaj ją z main
funkcji lub edytuj funkcję, jak chcesz jej używać.
#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);
}
System nazwij to!
system( "dir /b /s /a-d * > file_names.txt" );
Następnie po prostu przeczytaj plik.
EDYCJA: Tę odpowiedź należy uznać za włamanie, ale naprawdę działa (choć w sposób specyficzny dla platformy), jeśli nie masz dostępu do bardziej eleganckich rozwiązań.
Ponieważ pliki i podkatalogi katalogu są zwykle przechowywane w strukturze drzewa, intuicyjnym sposobem jest użycie algorytmu DFS do rekurencyjnego przechodzenia między nimi. Oto przykład w systemie operacyjnym Windows przy użyciu podstawowych funkcji plików w io.h. Możesz zastąpić te funkcje na innej platformie. Chcę wyrazić, że podstawowa idea DFS doskonale spełnia ten problem.
#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);
}
Próbowałem podążać za przykładem podanym w obu odpowiedziach i być może warto zauważyć, że wygląda na to, że std::filesystem::directory_entry
został zmieniony tak, aby nie miał przeciążenia <<
operatora. Zamiast tego std::cout << p << std::endl;
musiałem użyć następujących, aby móc skompilować i uruchomić:
#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;
}
próba przejścia p
sama, std::cout <<
powodując błąd braku przeładowania.
Opierając się na tym, co opublikował herohuyongtao i kilka innych postów:
http://www.cplusplus.com/forum/general/39766/
Jaki jest oczekiwany typ danych wejściowych FindFirstFile?
Jak przekonwertować ciąg na ciąg?
To jest rozwiązanie dla systemu Windows.
Ponieważ chciałem przekazać std :: string i zwrócić wektor ciągów, musiałem dokonać kilku konwersji.
#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
i FindNextFileA
. Wtedy nie będzie potrzeby konwertowania wyniku na wielobajtowy lub danych wejściowych na Unicode.
Po prostu coś, czym chcę się podzielić i dziękuję za lekturę. Pobaw się z tą funkcją, aby ją trochę zrozumieć. Może ci się spodobać e oznacza rozszerzenie, p oznacza ścieżkę, a s oznacza separator ścieżki.
Jeśli ścieżka zostanie przekazana bez kończącego separatora, do ścieżki zostanie dołączony separator. W przypadku rozszerzenia, jeśli zostanie wprowadzony pusty ciąg, funkcja zwróci dowolny plik, który nie ma rozszerzenia w nazwie. Jeśli wprowadzono pojedynczą gwiazdkę, wszystkie pliki w katalogu zostaną zwrócone. Jeśli długość e jest większa niż 0, ale nie jest pojedynczą *, kropka zostanie dodana do e, jeśli e nie zawierało kropki w pozycji zerowej.
Dla wartości zwracanej. Jeśli zostanie zwrócona mapa o zerowej długości, nic nie zostanie znalezione, ale katalog jest otwarty. Jeśli indeks 999 jest dostępny z wartości zwracanej, ale rozmiar mapy wynosi tylko 1, oznacza to, że wystąpił problem z otwarciem ścieżki katalogu.
Należy pamiętać, że w celu zwiększenia wydajności funkcję tę można podzielić na 3 mniejsze funkcje. Ponadto możesz utworzyć funkcję wywołującą, która wykryje, którą funkcję wywoła na podstawie danych wejściowych. Dlaczego to jest bardziej wydajne? Powiedziane, jeśli masz zamiar pobrać wszystko, co jest plikiem, wykonując tę metodę podfunkcja zbudowana do pobierania wszystkich plików po prostu pobierze wszystkie pliki i nie będzie musiała oceniać żadnego innego niepotrzebnego warunku za każdym razem, gdy znajdzie plik.
Dotyczy to także pobierania plików, które nie mają rozszerzenia. Specjalna wbudowana funkcja do tego celu oceniałaby tylko pod kątem pogody, czy znaleziony obiekt jest plikiem, a następnie czy nazwa pliku zawiera kropkę.
Oszczędność może nie być duża, jeśli czytasz tylko katalogi z mniejszą ilością plików. Ale jeśli czytasz dużą liczbę katalogów lub jeśli katalog zawiera kilkaset tysięcy plików, może to być ogromna oszczędność.
#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;
}
To zadziałało dla mnie. Zapisuje plik zawierający tylko nazwy (bez ścieżki) wszystkich plików. Następnie odczytuje ten plik txt i drukuje go dla ciebie.
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;
}
}