Home > Guides > Programming > C/C++

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Manipulating Directories

Last updated Jul 29, 2005.

Standard C++ doesn't have a library for manipulating directories. The closest thing you can get is Boost's filesystem library. However, most implementations nowadays support the quasi-standard <dirent.h> and <dir.h> libraries. These libraries, originally written in C, enable you to list the files in a directory, change the current directory, create a new directory and delete an existing directory.

Traversing a Directory

The <dirent.h> header declares functions for opening, reading, rewinding and closing a directory. To view the files in a directory, you have to open it first using the opendir() function:

DIR * opendir(const char * path);

opendir() returns a pointer to DIR. DIR is a data structure that represents a directory. A NULL return value indicates an error. path must be a name of an existing directory.

To traverse a successfully opened directory, use readdir():

struct dirent * readdir (DIR * pdir);

pdir is the pointer obtained from a previous opendir() call. readdir() returns a pointer to a dirent structure whose data member, d_name, contains the name of the current file (the rest of dirent's members depend on the specific file system installed on your machine so I won't discuss them here). Each successive call to readdir() advances to the next file in the directory.

readdir() returns NULL either in the event of an error or once you have traversed all the files in the directory. To distinguish between these two conditions, check errno after every readdir() call. Since readdir() changes errno only if an error has occurred, you need to reset it explicitly before each readdir() call.

The rewinddir() function resets a directory stream to the first entry:

void rewinddir(DIR *pdir);

rewinddir() also ensures that the directory accurately reflects any changes to the directory (file deletion, renaming etc.) since the last opendir() or rewinddir() calls.

Use closedir() to close the directory once you are done with it:

int closedir (DIR * pdir);

pdir is the pointer obtained from a previous opendir() call.

The following C program lists the contents of the current working directory:

#include <errno.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
 DIR *pdir;
 struct dirent *pent;

 pdir=opendir("."); //"." refers to the current dir
 if (!pdir){
 printf ("opendir() failure; terminating");
 exit(1);
 }
 errno=0;
 while ((pent=readdir(pdir))){
  printf("%s", pent->d_name);
 }
 if (errno){
 printf ("readdir() failure; terminating");
 exit(1);
 }
 closedir(pdir);
}

Create, Delete and Change a Directory

Other directory-related operations, such as creating, deleting, and changing a directory, are grouped in another quasi-standard library called <dir.h>. In POSIX systems, these functions are often declared in <unistd.h>.

The mkdir() function creates a new directory:

int mkdir(const char * dirname, [mode_t perm]);

dirname contains the new directory's name. An invalid directory name causes mkdir() to fail. perm indicates the directory's permissions. This argument exists only in the POSIX version of this function.

The function rmdir() deletes an existing directory:

int rmdir(const char * dirname);

rmdir() fails if the directory isn't empty. To remove a directory that contains files, you need to delete these files first and then call rmdir().

To obtain the full path name (including the drive) of the current working directory, call the getcwd() function:

char *getcwd(char *path, int num);

This function requires special attention. path is a char array of num characters. If the full pathname length (including the terminating '\0') is longer than num, the function call fails. If you don't know the pathname's length, pass NULL as the first argument. In this case, getcwd() uses malloc() to allocate a buffer large enough to store the current directory and returns its address to the caller. It's the caller's responsibility to release that buffer afterwards.

chdir() changes the process's current working directory:

int chdir(const char * dirname);

If dirname isn't a valid path name or if the process doesn't have the necessary permissions chdir() fails.

Summary

The <dirent.h> and <dir.h> legacy libraries lend themselves easily to an object-oriented face-lift. For instance, the opendir() and closedir() pair of functions fits neatly into the well-known Resource Acquisition is Initialization idiom. Similarly, instead of bare pointers, such as DIR* and dirent *, one could use iterators. An iterator-based interface would allow you to use ++ to advance to the next file, instead of calling readdir() repeatedly. More importantly, it would enable you to use STL algorithms to manipulate directories. Boost already offers a file-system library designed according to these principles. Hopefully, it will be incorporated into standard C++ in the future.

In the meantime, familiarity with these classic libraries is indispensable, especially if you're aiming at cross-platform solutions.

Discussions

Bugzilla
Posted Nov 18, 2008 01:53 AM by cupu
2 Replies
auto_ptr issues
Posted Sep 14, 2007 07:43 AM by singh_siddhu
1 Replies
i want c++ book through net
Posted Aug 23, 2007 11:13 PM by harivilu
3 Replies

Make a New Comment

You must log in in order to post a comment.

Related Resources

Danny KalevBjarne Stroustrups's Stevens Talk
By Danny KalevDecember 7, 2009 No Comments

On 2nd December Bjarne Stroustrup delivered a talk about the standardization process of C++0x at the Stevens institute. Here some of the key points from his talk.

Danny KalevMinutes from the October 2009 Meeting
By Danny KalevNovember 19, 2009 No Comments

The minutes from the Santa Cruz (October 2009) meeting are available here. Even if you're not a language layer at heart, I encourage you to read them.

Danny KalevA Reader's Opinion on Attributes
By Danny KalevOctober 20, 2009 No Comments

In August I dedicated a series to the debate about C++0x attributes. I believe that it covered the subject in a balanced and detailed way, but I keep getting complaints from C++ users who don't like attributes for various reasons. Here's a recent email I received from a Polish C++ programmer. While it  doesn't represent my opinion about attributes -- I'm rather neutral about this feature and consider it a "solution waiting for a problem" -- but it suggests that attributes are still a highly controversial issue that will haunt C++ for a long time. The email is quoted here with minor edits that and as usual, with all private details removed.

See More Blogs

Informit Network