How can I get the list of files in a directory using C or C++?

前端 未结 27 3152
情书的邮戳
情书的邮戳 2020-11-21 05:30

How can I determine the list of files in a directory from inside my C or C++ code?

I\'m not allowed to execute the ls command and parse the results from

相关标签:
27条回答
  • 2020-11-21 06:07

    UPDATE 2017:

    In C++17 there is now an official way to list files of your file system: std::filesystem. There is an excellent answer from Shreevardhan below with this source code:

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

    Old Answer:

    In small and simple tasks I do not use boost, I use dirent.h which is also available for 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;
    }
    

    It is just a small header file and does most of the simple stuff you need without using a big template-based approach like boost(no offence, I like boost!).

    The author of the windows compatibility layer is Toni Ronkko. In Unix, it is a standard header.

    0 讨论(0)
  • 2020-11-21 06:07

    For a C only solution, please check this out. It only requires an extra 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);
    

    Some advantages over other options:

    • It's portable - wraps POSIX dirent and Windows FindFirstFile
    • It uses readdir_r where available, which means it's (usually) threadsafe
    • Supports Windows UTF-16 via the same UNICODE macros
    • It is C90 so even very ancient compilers can use it
    0 讨论(0)
  • 2020-11-21 06:08

    This answer should work for Windows users that have had trouble getting this working with Visual Studio with any of the other answers.

    1. Download the dirent.h file from the github page. But is better to just use the Raw dirent.h file and follow my steps below (it is how I got it to work).

      Github page for dirent.h for Windows: Github page for dirent.h

      Raw Dirent File: Raw dirent.h File

    2. Go to your project and Add a new Item (Ctrl+Shift+A). Add a header file (.h) and name it dirent.h.

    3. Paste the Raw dirent.h File code into your header.

    4. Include "dirent.h" in your code.

    5. Put the below void filefinder() method in your code and call it from your main function or edit the function how you want to use it.

      #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);
      }
      
    0 讨论(0)
  • 2020-11-21 06:10

    Since files and sub directories of a directory are generally stored in a tree structure, an intuitive way is to use DFS algorithm to recursively traverse each of them. Here is an example in windows operating system by using basic file functions in io.h. You can replace these functions in other platform. What I want to express is that the basic idea of DFS perfectly meets this 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);
    }
    
    0 讨论(0)
  • 2020-11-21 06:11

    Check out this class which uses the win32 api. Just construct an instance by providing the foldername from which you want the listing then call the getNextFile method to get the next filename from the directory. I think it needs windows.h and 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;
        }
    
    };
    
    0 讨论(0)
  • 2020-11-21 06:11

    Shreevardhan answer works great. But if you want to use it in c++14 just make a change namespace fs = experimental::filesystem;

    i.e.,

    #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;
    }
    
    0 讨论(0)
提交回复
热议问题