Wie kann ich die Liste der Dateien in einem Verzeichnis in meinem C- oder C++-Code ermitteln?
Ich darf das Programm nicht ausführen. ls
Befehl und analysiere die Ergebnisse in meinem Programm.
Wie kann ich die Liste der Dateien in einem Verzeichnis in meinem C- oder C++-Code ermitteln?
Ich darf das Programm nicht ausführen. ls
Befehl und analysiere die Ergebnisse in meinem Programm.
UPDATE 2017 :
In C++17 gibt es nun eine offizielle Möglichkeit, Dateien des Dateisystems aufzulisten: std::filesystem
. Es gibt eine ausgezeichnete Antwort von Shreevardhan unten mit diesem Quellcode:
#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; }
Alte Antwort:
Bei kleinen und einfachen Aufgaben verwende ich keinen Boost, sondern dirent.h . Es ist als Standard-Header in UNIX verfügbar und auch für Windows über ein Kompatibilitätsebene erstellt von Toni Ronkko .
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;
}
Es ist nur eine kleine Header-Datei und erledigt die meisten der einfachen Dinge, die Sie brauchen, ohne einen großen Template-basierten Ansatz wie boost zu verwenden (nichts für ungut, ich mag boost!).
C++17 hat jetzt eine std::filesystem::directory_iterator
die verwendet werden können als
#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;
}
Auch, std::filesystem::recursive_directory_iterator
kann auch die Unterverzeichnisse durchlaufen.
Leider definiert der C++-Standard keine Standardmethode für die Arbeit mit Dateien und Ordnern auf diese Weise.
Da es keinen plattformübergreifenden Weg gibt, ist der beste plattformübergreifende Weg die Verwendung einer Bibliothek wie der boost-Dateisystem-Modul .
Plattformübergreifende Boost-Methode:
Die folgende Funktion, die einen Verzeichnispfad und einen Dateinamen angibt, durchsucht das Verzeichnis und seine Unterverzeichnisse rekursiv nach dem Dateinamen und gibt ein bool und bei Erfolg den Pfad zur gefundenen Datei zurück.
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; }
Quelle ist die oben erwähnte Boost-Seite.
Für Unix/Linux-basierte Systeme:
Sie können verwenden opendir / readdir / closedir .
Der Beispielcode, der ein Verzeichnis nach dem Eintrag ``Name'' durchsucht, lautet:
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;
Quellcode aus den oben genannten Manpages.
Für ein Windows-basiertes System:
Sie können die Win32-API verwenden FindFirstFile / FindNextFile / FindClose Funktionen.
Das folgende C++-Beispiel zeigt Ihnen eine minimale Verwendung von 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); } }
Quellcode von den oben genannten msdn-Seiten.
Eine Funktion reicht aus, Sie müssen keine Bibliothek eines Drittanbieters (für Windows) verwenden.
#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: wie von @Sebastian erwähnt, könnten Sie die *.*
a *.ext
um nur die EXT-Dateien (d. h. eines bestimmten Typs) in diesem Verzeichnis zu erhalten.
Eine Lösung, die nur in C funktioniert, finden Sie hier. Sie erfordert nur einen zusätzlichen Header:
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);
Einige Vorteile gegenüber anderen Optionen:
readdir_r
wo verfügbar, was bedeutet, dass es (normalerweise) thread-sicher istUNICODE
Makros CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.