817 Stimmen

Wie kann ich die Liste der Dateien in einem Verzeichnis mit C oder C++ erhalten?

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.

1108voto

Peter Parker Punkte 27790

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!).

523voto

Shreevardhan Punkte 11363

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.

240voto

Brian R. Bondy Punkte 325712

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.

107voto

herohuyongtao Punkte 47389

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.

61voto

congusbongus Punkte 11902

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:

  • Es ist portabel - wickelt POSIX dirent und Windows FindFirstFile
  • Sie verwendet readdir_r wo verfügbar, was bedeutet, dass es (normalerweise) thread-sicher ist
  • Unterstützt Windows UTF-16 über das gleiche UNICODE Makros
  • Es handelt sich um C90, so dass selbst sehr alte Compiler es verwenden können.

CodeJaeger.com

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.

Powered by:

X