Bagaimana saya bisa menentukan daftar file dalam direktori dari dalam kode C atau C ++ saya?
Saya tidak diizinkan untuk mengeksekusi ls
perintah dan mem-parsing hasil dari dalam program saya.
Bagaimana saya bisa menentukan daftar file dalam direktori dari dalam kode C atau C ++ saya?
Saya tidak diizinkan untuk mengeksekusi ls
perintah dan mem-parsing hasil dari dalam program saya.
Jawaban:
Dalam tugas-tugas kecil dan sederhana saya tidak menggunakan boost, saya menggunakan dirent.h yang juga tersedia untuk 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;
}
Ini hanya file header kecil dan melakukan sebagian besar hal-hal sederhana yang Anda butuhkan tanpa menggunakan pendekatan berbasis template besar seperti boost (jangan tersinggung, saya suka boost!).
Penulis lapisan kompatibilitas windows adalah Toni Ronkko. Di Unix, itu adalah header standar.
PEMBARUAN 2017 :
Dalam C ++ 17 sekarang ada cara resmi untuk daftar file dari sistem file Anda: std::filesystem
. Ada jawaban yang sangat baik dari Shreevardhan di bawah ini dengan kode sumber ini:
#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
, dengan C ++ 17 ada std::filesystem
. Lihat jawaban Shreevardhan di bawah ini. Jadi tidak perlu untuk perpustakaan pihak ke-3.
C ++ 17 sekarang memiliki std::filesystem::directory_iterator
, yang dapat digunakan sebagai
#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;
}
Juga, std::filesystem::recursive_directory_iterator
dapat mengulangi subdirektori juga.
namespace fs = std::experimental::filesystem;
. Tampaknya berfungsi ok.
std::filesystem::path
ke std::cout
, tanda kutip termasuk dalam output. Untuk menghindarinya, tambahkan .string()
jalur untuk melakukan konversi eksplisit dan bukan implisit (di sini std::cout << p.string() << std::endl;
). Contoh: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
std::wstring
boleh digunakan atau apa jenis dari iterator?
-lstdc++fs
, saya akan mendapatkan SIGSEGV (Address boundary error)
. Saya tidak dapat menemukan di mana pun dalam dokumentasi bahwa ini diperlukan, dan tautan tidak memberikan petunjuk apa pun. Ini bekerja untuk keduanya g++ 8.3.0
dan clang 8.0.0-3
. Apakah ada yang punya wawasan ke mana hal-hal seperti ini ditentukan dalam dokumen / spesifikasi?
Sayangnya standar C ++ tidak mendefinisikan cara standar untuk bekerja dengan file dan folder dengan cara ini.
Karena tidak ada cara lintas platform, cara lintas platform terbaik adalah dengan menggunakan perpustakaan seperti modul sistem file boost .
Metode peningkatan lintas platform:
Fungsi berikut, diberi jalur direktori dan nama file, secara rekursif mencari direktori dan sub-direktori untuk nama file, mengembalikan bool, dan jika berhasil, path ke file yang ditemukan.
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; }
Sumber dari halaman boost yang disebutkan di atas.
Untuk sistem berbasis Unix / Linux:
Anda dapat menggunakan opendir / readdir / closedir .
Kode sampel yang mencari direktori untuk entri `` name '' adalah:
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;
Kode sumber dari halaman manual di atas.
Untuk sistem berbasis windows:
Anda dapat menggunakan fungsi Win32 API FindFirstFile / FindNextFile / FindClose .
Contoh C ++ berikut ini menunjukkan kepada Anda penggunaan FindFirstFile yang minimal.
#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); } }
Kode sumber dari halaman msdn di atas.
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, dengan C ++ 17 ada std::filesystem
, yang memiliki fungsi yang sama dengan boost (libs berasal dari boost). Lihat jawaban Shreevardhan di bawah ini.
Satu fungsi sudah cukup, Anda tidak perlu menggunakan perpustakaan pihak ke-3 (untuk 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: seperti yang disebutkan oleh @Sebastian, Anda bisa mengubah *.*
ke *.ext
untuk mendapatkan hanya file EXT (yaitu dari jenis tertentu) di direktori itu.
std::vector<std::wstring>
dan fileName.c_str()
bukannya vektor string, yang tidak akan dikompilasi.
Untuk solusi C saja, silakan periksa ini. Hanya membutuhkan tajuk tambahan:
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);
Beberapa keunggulan dibandingkan opsi lain:
readdir_r
mana tersedia, yang berarti itu (biasanya) threadsafeUNICODE
makro yang samaSaya sarankan menggunakan glob
pembungkus yang dapat digunakan kembali ini. Ini menghasilkan yang vector<string>
sesuai dengan jalur file yang sesuai dengan pola 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;
}
Yang kemudian dapat dipanggil dengan pola wildcard sistem normal seperti:
vector<string> files = globVector("./*");
No such file or directory
. Bisakah Anda memberi tahu saya cara mengatasi masalah ini?
GLOB_TILDE
dengan GLOB_TILDE | GLOB_MARK
dan kemudian memeriksa jalur yang berakhir dengan garis miring. Anda harus membuat modifikasi untuk itu jika Anda membutuhkannya.
glob
.
Berikut ini adalah kode yang sangat sederhana dalam C++11
menggunakan boost::filesystem
perpustakaan untuk mendapatkan nama file dalam direktori (tidak termasuk nama folder):
#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;
}
}
Outputnya seperti:
file1.txt
file2.dat
boost::filesystem
perpustakaan boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm
Kenapa tidak digunakan 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;
}
Saya pikir, cuplikan di bawah ini dapat digunakan untuk mendaftar semua file.
#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);
}
Berikut ini adalah struktur dari 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 */
};
Coba tingkatkan untuk metode x-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
atau cukup gunakan file hal spesifik OS Anda.
Lihat kelas ini yang menggunakan api win32. Cukup buat instance dengan menyediakan foldername
dari mana Anda ingin listing kemudian panggil getNextFile
metode untuk mendapatkan yang berikutnya filename
dari direktori. Saya pikir itu perlu windows.h
dan 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;
}
};
Manual GNU FTW
Juga, kadang-kadang ada baiknya langsung ke sumbernya (pun intended). Anda dapat belajar banyak dengan melihat jeroan dari beberapa perintah yang paling umum di Linux. Saya telah membuat mirror sederhana dari GNU's coreutils di github (untuk membaca).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Mungkin ini tidak membahas Windows, tetapi sejumlah kasus menggunakan varian Unix dapat diperoleh dengan menggunakan metode ini.
Semoga itu bisa membantu ...
Jawaban Shreevardhan bekerja dengan sangat baik. Tetapi jika Anda ingin menggunakannya di c ++ 14, lakukan saja perubahannamespace fs = experimental::filesystem;
yaitu,
#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;
}
Saya harap kode ini membantu Anda.
#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
mengembalikan alamat variabel lokal. Juga, Anda mungkin harus menggunakan metode konversi yang tersedia di WinAPI alih-alih menulis metode Anda sendiri.
Implementasi ini mewujudkan tujuan Anda, secara dinamis mengisi serangkaian string dengan konten direktori yang ditentukan.
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
blok pertama . Saya menyebutnya denganchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Ini bekerja untuk saya. Maaf jika saya tidak dapat mengingat sumbernya. Mungkin dari halaman manual.
#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/");
}
Anda bisa mendapatkan semua file langsung di direktori root Anda dengan menggunakan std :: experimental :: filesystem :: directory_iterator (). Kemudian, baca nama pathfiles ini.
#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;
}
Jawaban ini seharusnya berfungsi untuk pengguna Windows yang mengalami kesulitan dalam menjalankan ini dengan Visual Studio dengan jawaban lain mana pun.
Unduh file dirent.h dari halaman github. Tetapi lebih baik hanya menggunakan file Raw dirent.h dan ikuti langkah-langkah saya di bawah ini (ini adalah cara saya membuatnya bekerja).
Halaman Github untuk dirent.h untuk Windows: Halaman Github untuk dirent.h
Raw Dirent File: Raw dirent.h File
Buka proyek Anda dan Tambahkan Item baru ( Ctrl+ Shift+ A). Tambahkan file header (.h) dan beri nama dirent.h.
Tempel kode file Raw dirent.h ke dalam header Anda.
Sertakan "dirent.h" dalam kode Anda.
Masukkan void filefinder()
metode di bawah ini dalam kode Anda dan panggil dari main
fungsi Anda atau edit fungsi bagaimana Anda ingin menggunakannya.
#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);
}
Sebut saja sistem itu!
system( "dir /b /s /a-d * > file_names.txt" );
Kemudian baca saja file tersebut.
EDIT: Jawaban ini harus dianggap sebagai peretasan, tetapi ini benar-benar berfungsi (walaupun dengan cara khusus platform) jika Anda tidak memiliki akses ke solusi yang lebih elegan.
Karena file dan sub direktori direktori umumnya disimpan dalam struktur pohon, cara intuitif adalah dengan menggunakan algoritma DFS untuk secara rekursif melintasi masing-masing. Berikut adalah contoh dalam sistem operasi windows dengan menggunakan fungsi file dasar di io.h. Anda dapat mengganti fungsi-fungsi ini di platform lain. Yang ingin saya ungkapkan adalah bahwa ide dasar DFS memenuhi masalah ini dengan sempurna.
#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);
}
Saya mencoba mengikuti contoh yang diberikan di kedua jawaban dan mungkin perlu dicatat bahwa tampaknya seolah-olah std::filesystem::directory_entry
telah diubah untuk tidak memiliki kelebihan <<
operator. Alih-alih std::cout << p << std::endl;
saya harus menggunakan yang berikut ini untuk dapat mengkompilasi dan membuatnya berfungsi:
#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;
}
mencoba meneruskan p
sendiri untuk std::cout <<
menghasilkan kesalahan kelebihan yang hilang.
Membangun apa yang diposting oleh herohuyongtao dan beberapa posting lainnya:
http://www.cplusplus.com/forum/general/39766/
Apa tipe input yang diharapkan dari FindFirstFile?
Bagaimana cara mengubah wstring menjadi string?
Ini adalah solusi Windows.
Karena saya ingin meneruskan std :: string dan mengembalikan vektor string, saya harus membuat beberapa konversi.
#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
dan FindNextFileA
. Maka Tidak perlu mengubah hasil menjadi multibyte atau Input ke unicode.
Hanya sesuatu yang ingin saya bagikan dan terima kasih atas bahan bacaannya. Bermain-main dengan fungsi untuk sedikit memahaminya. Anda mungkin menyukainya. e berdiri untuk ekstensi, p adalah untuk path, dan s adalah untuk path separator.
Jika jalur dilewatkan tanpa mengakhiri pemisah, pemisah akan ditambahkan ke jalur. Untuk ekstensi, jika string kosong dimasukkan maka fungsi akan mengembalikan file apa pun yang tidak memiliki ekstensi dalam namanya. Jika satu bintang dimasukkan dari semua file dalam direktori akan dikembalikan. Jika panjang e lebih besar dari 0 tetapi bukan satu * maka titik akan ditambahkan ke e jika e tidak mengandung titik di posisi nol.
Untuk nilai kembali. Jika peta nol panjang dikembalikan maka tidak ada yang ditemukan tetapi direktori terbuka oke. Jika indeks 999 tersedia dari nilai kembali tetapi ukuran peta hanya 1 maka itu berarti ada masalah dengan membuka jalur direktori.
Perhatikan bahwa untuk efisiensi, fungsi ini dapat dibagi menjadi 3 fungsi yang lebih kecil. Selain itu, Anda dapat membuat fungsi pemanggil yang akan mendeteksi fungsi mana yang akan dipanggil berdasarkan input. Mengapa itu lebih efisien? Mengatakan jika Anda akan mengambil semua yang merupakan file, melakukan metode itu subfungsi yang dibangun untuk mengambil semua file hanya akan mengambil semua file dan tidak perlu mengevaluasi kondisi lain yang tidak perlu setiap kali ditemukan file.
Itu juga berlaku ketika Anda mengambil file yang tidak memiliki ekstensi. Fungsi dibangun khusus untuk tujuan itu hanya akan mengevaluasi cuaca jika objek yang ditemukan adalah file dan kemudian apakah nama file memiliki titik di dalamnya.
Penghematan mungkin tidak banyak jika Anda hanya membaca direktori dengan tidak banyak file. Tetapi jika Anda membaca sejumlah besar direktori atau jika direktori tersebut memiliki beberapa ratus ribu file, ini bisa menjadi penghematan besar.
#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;
}
Ini berhasil untuk saya. Itu menulis file dengan hanya nama (tidak ada jalur) dari semua file. Kemudian ia membaca file txt itu dan mencetaknya untuk Anda.
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;
}
}