Creating, Deleting, and Changing a Directory
Some of the 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 declared in
<unistd.h>.
To create a new directory, use mkdir():
int mkdir(const char * dirname, [mode_t perm]);
dirname is the name of the directory to be created. If it's an existing file name or an invalid directory string,
mkdir() fails. The
perm argument is used in POSIX systems to specify the directory's permissions. It doesn't exist in the Windows version of this function.
To delete an existing directory, use rmdir():
int rmdir(const char * dirname);
The directory must be empty. Otherwise,
rmdir() fails.
The getcwd() function retrieves the full path name (including the drive) of the current working directory:
char *getcwd(char *path, int num);
This function is tricky and requires special attention. The
path argument points to an array of
num characters. If the full pathname length (including the terminating '\0') is longer than
num bytes, an error occurs. Alternatively,
path can be
NULL. In this case,
getcwd() uses
malloc() to allocate a buffer large enough to store the current directory. The only snag is that you have to call
free(path) afterwards.
To set a different working directory, use chdir():
int chdir(const char * dirname);
chdir() sets
dirname as the current working directory of the process. If
dirname isn't a valid path name or if the process doesn't have the right permissions,
chdir() fails.
Paths will Cross
You're probably wondering why I have adhered to pure C code in this solution. My aim was to show that even state-of-the-art ISO C++ doesn't always offer viable alternatives to vintage C libraries. However, these C libraries can be used as the underlying machinery of a higher level object-oriented interface since they lend themselves easily to various design idioms that I've discussed before.
For example, instead of the cumbersome errno mechanism, you can design a hierarchy of exception classes to automate error handling. Similarly, the opendir() and closedir() pair fits neatly into the well-known Resource Acquisition Is Initialization idiom.
Finally, instead of bare DIR* and dirent * pointers, use iterators. This way, you can use ++ to advance to the next file instead of calling readdir() repeatedly. Notational convenience not withstanding, the use of iterators also enables you to exert the power of STL algorithms. Boost already offers a file-system library designed according to these principles. Hopefully, it will be incorporated into standard C++ in the future. Until then, the <dirent.h> and <dir.h> libraries presented here will serve you well if you're aiming at portable and platform-neutral code.