Reading the Contents of a Directory


You need to read the contents of a directory, most likely to do something to each file or subdirectory that's in it.


To write something portable, use the Boost Filesystem library's classes and functions. It provides a number of handy utilities for manipulating files, such as a portable path representation, directory iterators, and numerous functions for renaming, deleting, and copying files, and so on. Example 10-19 demonstrates how to use a few of these facilities.

Example 10-19. Reading a directory


using namespace boost::filesystem;

int main(int argc, char** argv) {

 if (argc < 2) {
 std::cerr << "Usage: " << argv[0] << " [dir name]

 path fullPath = // Create the full, absolute path name
 system_complete(path(argv[1], native));

 if (!exists(fullPath)) {
 std::cerr << "Error: the directory " << fullPath.string( )
 << " does not exist.

 if (!is_directory(fullPath)) {
 std::cout << fullPath.string( ) << " is not a directory!

 directory_iterator end;
 for (directory_iterator it(fullPath);
 it != end; ++it) { // Iterate through each
 // element in the dir,
 std::cout << it->leaf( ); // almost as you would
 if (is_directory(*it)) // an STL container
 std::cout << " (dir)";
 std::cout << '




Like creating or deleting directories (see Recipe 10.10 and Recipe 10.11), there is no standard, portable way to read the contents of a directory. To make your C++ life easier, the Filesystem library in the Boost project provides a set of portable routines for operating on files and directories. It also provides many moresee the other recipes in this chapter or the Boost Filesystem web page at for more information.

Example 10-19 is a simple directory listing program (like ls on Unix or dir on MS-DOS). First, it builds an absolute pathname out of the argument passed to the program, like this:

path fullPath = complete(path(argv[1], native));

The data type of a path is called, appropriately, path. This is the type that the filesystem routines operate on, and is easily convertible to a string by calling path::string. Once the path has been assembled, the program checks its existence (with exists), then checks to see if it is a directory with another utility function, is_directory. If it is, then everything is in good shape and it can proceed to the real work of listing the directory contents.

There is a class called directory_iterator in filesystem that uses standard iterator semantics, like the standard containers, to allow you to use an iterator like you would a pointer to a directory element. Unlike standard containers, however, there is no end member function you can call on a directory that represents one-past-the-last-element (i.e., vector::end). Instead, if you create a directory_iterator with the default constructor, it represents an end marker that you can use for comparison to determine when you are done. So do this:

directory_iterator end;

and then you can create an iterator from your path, and compare it to end, like this:

for (directory_iterator it(fullPath);
 it != end; ++it) {
 // do whatever you want to *it
 std::cout << it->leaf( );

The leaf member function returns a string representing the element referred to by a path, and not the full path itself, which is what you get if you call the string member function.

If you have to write something that is portable, but for some reason you cannot use Boost, take a look at the Boost code itself. It contains #ifdefs that deal with (for the most part) Windows versus Posix OS interface environments and path particulars, such as drive letters versus device names.

See Also

Recipe 10.10 and Recipe 10.11

Building C++ Applications

Code Organization


Strings and Text

Dates and Times

Managing Data with Containers



Exceptions and Safety

Streams and Files

Science and Mathematics






C++ Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2006
Pages: 241 © 2008-2020.
If you may any questions please contact us: