Monday, April 11, 2011

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

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 within my program.

From stackoverflow
  • Try boost for x-platform method

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

    or just use your OS specific file stuff.

    samoz : That link crashes my Firefox window. *doh*
    Tim : ok, i took out the other one and left the boost link
  • Unfortunately the C++ standard does not define a standard way of working with files and folders in this way.

    Since there is no cross platform way, the best cross platform way is to use a library such as the boost filesystem module.

    Cross platform boost method:

    The following function, given a directory path and a file name, recursively searches the directory and its sub-directories for the file name, returning a bool, and if successful, the path to the file that was found.

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

    Source from the boost page mentioned above.


    For Unix/Linux based systems:

    You can use opendir / readdir / closedir.

    Sample code which searches a directory for entry ``name'' is:

       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;
    

    Source code from the above man pages.


    For a windows based systems:

    you can use the Win32 API FindFirstFile / FindNextFile / FindClose functions.

    The following C++ example shows you a minimal use of 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);
       }
    }
    

    Source code from the above msdn pages.

  • 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;
     dir = opendir ("c:\\src\\");
    if (dir != 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!). I googled and found some links here The author of the windows compatibility layer is Toni Ronkko. In unix it is a standard-header

    Subtwo : +1: I like the lightweight solution. However, it requires an extra third party addition... But I guess you can't have it both ways. Anyway, good suggestion.
  • This is a duplicate of 609236

0 comments:

Post a Comment