C və ya C ++ istifadə edərək bir kataloqdakı faylların siyahısını necə əldə edə bilərsən?

C və ya C ++ kodlarımdan bir kataloqdakı faylların siyahısını necə müəyyənləşdirmək olar?

Mən ls yerinə yetirmək və nəticələri mənim proqramdan təhlil etməyə icazə ls .

481
04 марта '09 в 22:35 2009-03-04 22:35 Samoz 04 mart '09 saat 10:35 'da qurulacaq , 2009-03-04 22:35
@ 24 cavab

Kiçik və sadə tapşırıqlarda boost istifadə etmirəm, dirent.h istifadə edirəm, bu da pəncərələr üçün də mövcuddur:

 DIR *dir; struct dirent *ent; if ((dir = opendir ("c:\\src\\")) != NULL) {  while ((ent = readdir (dir)) != NULL) { printf ("%s\n", ent->d_name); } closedir (dir); } else {  perror (""); return EXIT_FAILURE; } 

Bu gücləndirmək kimi bir şablon əsaslı yanaşma istifadə etmədən ən sadə tapşırıqları yerinə yetirən kiçik bir başlıq faylıdır (heç bir pozuntu, məni sevirəm!).

Pəncərə uyğunluğu təbəqəsinin müəllifi Tony Ronkko. Unix'te standart başlıq.

2017 yenilənməsi :

C ++ 17 indi fayl sistem fayllarını qeyd etmək üçün rəsmi yola malikdir: std::filesystem . Aşağıdakılar Şreevardandan bu mənbə kodu ilə böyük cavabdır:

 #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; } 
674
04 марта '09 в 22:57 2009-03-04 22:57 cavab Peter Parker 04 mart '09 saat 22:57 'də verilmişdir 2009-03-04 22:57

C ++ 17-də hazırda std::filesystem::directory_iterator kimi istifadə edilə bilər

 #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; } 
border=0

Bundan əlavə, std::filesystem::recursive_directory_iterator alt dizinler vasitəsilə yineleyebilir.

226
28 мая '16 в 5:41 2016-05-28 05:41 Shreevardhan tərəfindən verilmiş cavab 28 may '16 saat 05:41 'də 2016-05-28 05:41

Təəssüf ki, C ++ standartı bu şəkildə fayl və qovluqlarla işləmək üçün standart üsulu müəyyən etmir.

Heç bir cross-platform yolu olmadığından, ən yaxşı cross-platform yolu fayl sistemi modulu boost kimi bir kitabxana istifadə etməkdir.

Cross Platform Metodu:

Kataloq yolu və fayl adı üçün göstərilən aşağıdakı funksiya recursively faylın adını dizin və onun alt dizinləri üçün axtarış edir, bool qaytarır və müvəffəqiyyətli halda aşkar faylın yolunu axtarır.

 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; } 

Yuxarıdakı səhifədən mənbə artır.


Unix / Linux əsaslı sistemlər üçün:

Opendir / readdir / closedir istifadə edə bilərsiniz.

'' Adı '' yazmaq üçün bir qovluğu axtaran nümunə kodu:

  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; 

Yuxarıda göstərilən əl səhifələrdən mənbə kodu.


Windows əsaslı sistemləri üçün:

FindFirstFile / FindNextFile / FindClose Win32 API funksiyalarını istifadə edə bilərsiniz.

Aşağıdakı C ++ nümunəsi FindFirstFile-nin minimal istifadəsini göstərir.

 #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],  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); } } 

Yuxarıda göstərilən msdn səhifələrinin mənbə kodu.

219
04 марта '09 в 22:38 2009-03-04 22:38 04 mart 09: 09-da Brian R. Bondy- ə cavab verərək, 2009-03-04 22:38

Bir funksiyanı kifayət edir, üçüncü tərəf kitabxanasından istifadə etmək lazım deyil (Windows üçün).

 #include <Windows.h> vector<string> get_all_files_names_within_folder(string folder) { vector<string> names; string search_path = folder + " off_t d_off;  unsigned short d_reclen;  unsigned char d_type;  char d_name[256];  }; 
16
23 окт. Şikant tərəfindən 23 oktyabrda cavab verildi 2013-10-23 09:36 '13 saat 09:36 'da 2013-10-23 09:36

X-platform üsulu üçün təşviq edin.

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

və ya yalnız xüsusi dosyanızın fayllarını istifadə edin.

10
04 марта '09 в 22:37 2009-03-04 22:37 cavab 04 mart '09 saat 22:37 'də Tim tərəfindən verilmişdir 2009-03-04 22:37

Win32 api istifadə edən bu sinifə baxın. Yazdırmaq istədiyiniz qovluq filename getNextFile sadəcə bir nümunə yaradın, sonra növbəti filename getNextFile üçün getNextFile metodunu getNextFile . Hesab edirəm ki, o, windows.hstdio.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, //skip . FindNextFileA(hfind, } int getNextFile(char* fname){ //skips .. when called for the first time chk=FindNextFileA(hfind, if (chk) strcpy(fname, found.cFileName); return chk; } }; 
8
08 апр. cavab robertvarga 08 apr verilir . 2011-04-08 19:48 '11 at 19:48 2011-04-08 19:48

GNU Manual FTW

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

Bundan əlavə, bəzən mənbəyə doğru getmək yaxşıdır. Linux'daki en yaygın komutların içlerini inceleyerek çox şey öğrenebilirsiniz. Github'da (oxumaq üçün) sadə GNU coreutils aynası yaratdım.

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

Bəlkə də bu, Windows-a tətbiq edilmir, lakin bu üsulları istifadə edərkən Unix variantlarını istifadə etmək üçün bir neçə variantdan istifadə edə bilərsiniz.

Ümid edirəm bu kömək edir ...

6
12 нояб. cavab Homer6 12 noyabrda verilir. 2012-11-12 00:35 '12 at 0:35 2012-11-12 00:35
 char **getKeys(char *data_dir, char* tablename, int *num_keys) { char** arr = malloc(MAX_RECORDS_PER_TABLE*sizeof(char*)); int i = 0; for (;i < MAX_RECORDS_PER_TABLE; i++) arr[i] = malloc( (MAX_KEY_LEN+1) * sizeof(char) ); char *buf = (char *)malloc( (MAX_KEY_LEN+1)*sizeof(char) ); snprintf(buf, MAX_KEY_LEN+1, "%s/%s", data_dir, tablename); DIR* tableDir = opendir(buf); struct dirent* getInfo; readdir(tableDir); // ignore '.' readdir(tableDir); // ignore '..' i = 0; while(1) { getInfo = readdir(tableDir); if (getInfo == 0) break; strcpy(arr[i++], getInfo->d_name); } *(num_keys) = i; return arr; } 
4
30 марта '12 в 0:12 2012-03-30 00:12 Cavab JasonYen2205 30 mart 2012 -ci ildə 0:12 2012-03-30 00:12 tərəfindən verilir

Ümid edirəm bu kod sizə kömək edir.

 #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  { 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,  vector<string> listFileNames; listFileNames.push_back(wchar_t2string(FindFileData.cFileName)); while (FindNextFile(hFind,  listFileNames.push_back(wchar_t2string(FindFileData.cFileName)); return listFileNames; } void main() { vector<string> listFiles; listFiles = listFilesInDirectory("C:\\*.txt"); for each (string str in listFiles) cout << str << endl; } 
3
19 февр. cavab Yas 19 feb verilir . 2012-02-19 21:22 '12 saat 21:22 'da 2012-02-19 21:22

Std :: experimental :: fileystem :: directory_iterator () istifadə edərək kök dizindəki bütün birbaşa faylları əldə edə bilərsiniz. Sonra bu yol fayllarının adını oxuyun.

 #include <iostream> #include <filesystem> #include <string> #include <direct.h> using namespace std; namespace fs = std::experimental::filesystem; void ShowListFile(string path) { for(auto  fs::directory_iterator(path))  cout<<p.path().filename()<<endl; // get file name } int main() { ShowListFile("C:/Users/dell/Pictures/Camera Roll/"); getchar(); return 0; } 
2
20 апр. 20 apreldə ducPham tərəfindən verilmiş cavab 2018-04-20 21:04 '18 saat 09:04 'da 2018-04-20 21:04

Mənim üçün işləyir. Məni xatırlamıramsa bağışlayın. Bu, yəqin ki, man səhifəsindən.

 #include <ftw.h> int AnalizeDirectoryElement (const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { if (tflag == FTW_F) { std::string strFileName(fpath); DoSomethingWith(strFileName); } return 0; } void WalkDirectoryTree (const char * pchFileName) { int nFlags = 0; if (nftw(pchFileName, AnalizeDirectoryElement, 20, nFlags) == -1) { perror("nftw"); } } int main() { WalkDirectoryTree("some_dir/"); } 
2
22 мая '17 в 7:44 2017-05-22 07:44 Cavab 22 may, 22 saat 07:44 2017-05-22 07:44 tarixində verilir

Şreevardanın cavabı böyük işləyir. Ancaq C ++ 14-də istifadə etmək istəyirsinizsə, namespace fs = experimental::filesystem; yaradın namespace fs = experimental::filesystem; namespace fs = experimental::filesystem; dəyişməsi namespace fs = experimental::filesystem;

yəni,

 #include <string> #include <iostream> #include <filesystem> using namespace std; namespace fs = experimental::filesystem; int main() { string path = "C:\\splits\\"; for (auto  p : fs::directory_iterator(path)) cout << p << endl; int n; cin >> n; } 
2
13 марта '18 в 9:38 2018-03-13 09:38 Cavab Venkat Vinay tərəfindən 13 Mart, '18 saat 9:38 ; 2018-03-13 09:38 'də verilir

Bu tətbiq müəyyən dizinin məzmunu ilə strings bir sıra dinamik doldurulması ilə məqsədi həyata keçirir.

 int exploreDirectory(const char *dirpath, char ***list, int *numItems) { struct dirent **direntList; int i; errno = 0; if ((*numItems = scandir(dirpath,  NULL, alphasort)) == -1) return errno; if (!((*list) = malloc(sizeof(char *) * (*numItems)))) { fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath); exit(EXIT_FAILURE); } for (i = 0; i < *numItems; i++) { (*list)[i] = stringDuplication(direntList[i]->d_name); } for (i = 0; i < *numItems; i++) { free(direntList[i]); } free(direntList); return 0; } 
2
13 сент. Giacomo Marciani tərəfindən verilmiş cavab sentyabr 13 2014-09-13 18:08 '14 at 18:08 2014-09-13 18:08

Bu cavab Visual Studio-dan bu işi başqa cür cavablarla ala bilməyən Windows istifadəçiləri üçün işləməlidir.

  1. Github səhifəsindən dirent.h faylını yükləyin. Amma yalnız Raw dirent.h faylını istifadə etmək və mənim adımları izləmək daha yaxşıdır (mənim işim necə oldu).

    Windows üçün dirent.h üçün Github page : dirent.h üçün Github page

    Raw Dirent faylı: Raw dirent.h faylı

  2. Layihəyə gedin və yeni element ( Ctrl + Shift + A ) əlavə edin. Başlıq faylını əlavə edin (.h) və onu dirent.h adını verin.

  3. Raw dirent.h kodunu başlığınıza yapışdırın.

  4. Kodunuza "dirent.h" daxil edin.

  5. void filefinder() metodunu void filefinder() və onu main funksiyadan çağırın və ya istifadə etmək istədiyiniz funksiyanı void filefinder() .

     #include <stdio.h> #include <string.h> #include "dirent.h" string path = "C:/folder"; //Put a valid path here for folder void filefinder() { DIR *directory = opendir(path.c_str()); struct dirent *direntStruct; if (directory != NULL) { while (direntStruct = readdir(directory)) { printf("File Name: %s\n", direntStruct->d_name); //If you are using <stdio.h> //std::cout << direntStruct->d_name << std::endl; //If you are using <iostream> } } closedir(directory); } 
1
04 сент. cavab ZKR 04 sep verilir . 2018-09-04 03:24 '18 də 3:24 2018-09-04 03:24 'də

Sistem çağırışı!

 system( "dir /b /s /ad * > file_names.txt" ); 

Sonra faylını oxuyun.

EDIT: Bu cavabı oğurluq hesab etməli, amma daha zərif həllərə çıxmağınız yoxdursa, işi (mütləq platformada olsa) edir.

1
03 июля '14 в 18:40 2014-07-03 18:40 Cavab Catalyst tərəfindən verilir 03 iyul '08 18:40 2014-07-03 18:40

Yalnız oxumaq materialına görə bölüşmək və təşəkkür etmək istəyirəm. Anlamaq üçün funksiya ilə oynayır. Bunu sevə bilərsiniz. e uzadılması, yol üçün p, və yolun məhdudlaşdırıcısı üçün dayanmışdı.

Yol ayrıcını bitirmədən keçirsə, yola bir ayırıcı əlavə olunacaq. Bir boşluq üçün boş bir simli girildikdə funksiya adında bir uzantı olmayan hər hansı bir fayl qaytarır. Bir ulduz girildikdə, kataloqdakı bütün fayllar qaytarılacaq. E uzunluq e 0'dan böyük olsa da, bir deyil *, əgər nöqtə sıfır mövqedə bir nöqtə içərsə, nöqtə e əlavə ediləcək.

Dönüş dəyəri üçün. Bir sıfır uzunluqlu xəritə qaytarılırsa, heç bir şey tapılmadı, ancaq kataloq normal olaraq açıldı. İndeks 999 qaytarma dəyərindən əldə edilsə, lakin xəritə ölçüsü yalnız 1dirsə, bu, kataloq yolunun açılması ilə bağlı bir problem var.

Xahiş edirik, məhsuldarlıq üçün bu funksiyanı 3 kiçik funksiyaya bölmək olar. Bundan əlavə, girişə əsaslanan zəng funksiyasını təyin edəcək bir zəng funksiyası yarada bilərsiniz. Niyə daha səmərəlidir? Bu üsulla faylın hər şeyi ələ keçirəcəyini deyirsinizsə, bütün faylları ələ keçirmək üçün yaradılan alt funksiya sadəcə bütün faylları ələ keçirəcək və hər bir fayl tapdıqda hər hansı bir lazımsız vəziyyətin qiymətləndirilməsinə ehtiyac yoxdur.

Bu da uzantısı olmayan faylları götürdükdə də tətbiq olunur. Bu məqsəd üçün xüsusi quraşdırılmış funksiya, obyektin bir fayl olduğu təqdirdə hava şəraitini qiymətləndirir və sonra bir fayl adının olub olmadığını qiymətləndirir.

Yalnız çox faylları olan dizinləri oxuyursanız, qənaət çox böyük ola bilməz. Ancaq kütləvi bir sıra dizinləri oxuduğunuzda və ya dizindəki bir neçə yüz min fayl varsa, bu böyük bir qənaət ola bilər.

 #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(),  == 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  for (const auto  : m) { std::cout << "m[" << p.first << "] = " << p.second << std::endl; } } int main(){ std::map<int, std::string> k = getFile("./", ""); printMap(k); return 0; } 
0
29 сент. Kevin Ng tərəfindən verilmiş cavab Sep 29 2018-09-29 13:54 '18 saat 13:54 'da 2018-09-29 13:54

Dizinin faylları və alt qovluqları adətən ağac quruluşunda saxlanıldıqları üçün, intuitiv bir şəkildə DFS alqoritmini təkrarlanan şəkildə hər birinə keçmək üçün istifadə etməkdir. Burada io.h. əsas fayl funksiyalarını istifadə edərək, Windows əməliyyat sistemindəki bir nümunədir. Bu xüsusiyyətləri digər platformada əvəz edə bilərsiniz. DFS'nin əsas fikri bu problem ilə əla iş tapdığını ifadə etmək istəyirəm.

 #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(), //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,  == 0); // _findclose(handle); } 
0
10 апр. Tkingcer tərəfindən verilən cavabı Apr 10 2018-04-10 18:16 '18 saat 6:16 'da 2018-04-10 18:16

Hər iki cavabda verilmiş nümunəyə riayət etməyə çalışdım və std::filesystem::directory_entry operatoru yükləmək üçün dəyişdirilmişdir kimi görünə bilər. std::cout << p << std::endl; Tərtib etmək və işləmək üçün aşağıdakılardan istifadə etmək məcburiyyətindəyəm:

 #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; } 

p özünə keçməyə çalışırdı, std::cout << heç bir yükləmə səhvinə səbəb oldu.

0
25 сент. Cavab StarKiller4011 25 Sentyabr verilir. 2018-09-25 16:10 '18 saat 16:10 'da 2018-09-25 16:10

Mənim üçün çalışdı. Bütün faylların adlarını (yolsuzluq) olan bir fayl yazır. Sonra bu txt faylını oxuyur və sizin üçün yazır.

 void DisplayFolderContent() { system("dir /n /b * > file_names.txt"); char ch; std::fstream myStream("file_names.txt", std::fstream::in); while (myStream.get(ch)) { std::cout << ch; } } 
-1
28 июня '17 в 8:23 2017-06-28 08:23 Cavab Cesar Alejandro Montero Orozco tərəfindən 28 İyun '17' də saat 8: 23- də verilir. 2017-06-28 08:23

Etiketler haqqında digər suallar və ya bir sual