- Overview
- Table of Contents
- Special Member Functions: Constructors, Destructors, and the Assignment Operator
- Operator Overloading
- Memory Management
- Templates
- Namespaces
- Time and Date Library
- Streams
- Object-Oriented Programming and Design Principles
- The Standard Template Library (STL) and Generic Programming
- Exception Handling
- Runtime Type Information (RTTI)
- Signal Processing
- Creating Persistent Objects
- Bit Fields
- New Cast Operators
- Environment Variables
- Variadic Functions
- Pointers to Functions
- Function Objects
- Pointers to Members
- Lock Files
- Design Patterns
- Dynamic Linking
- Tips and Techniques
- Using the Swap() Algorithm
- Using class stopwatch for Performance Measurements
- Extending <iostream> to Support User-Defined Types
- Using auto_ptr To Automate Memory Management
- Using auto_ptr To Automate Memory Management, Part II
- Using auto_ptr To Automate Memory Management, Part III
- Using enums as Mnemonic Indexes
- Create Objects on Pre-Allocated Memory Using Placement-new
- Online Books: Placement-new
- Bitwise Operators
- Bitwise Operators II
- Who's this?
- A Reference Guide
- The Virtues of Multiple Inheritance
- Interfaces
- Multiple Inheritance: Construction and Destruction Order
- nothrow new
- POD Initialization
- Object Initialization
- const Declarations
- The Semantics of volatile
- inline Functions
- Project Organization Guidelines
- All About bool
- typedef Declarations
- State of the union
- Dynamic Cast Uses
- Integrating C and C++
- const-Correctness
- const-Correctness: Advanced Issues
- Sprucing Up Legacy Code
- Virtual Constructors
- Naming Names
- Function Calls
- Speaking Standardese (updated)
- Speaking Standardese: the One Definition Rule
- Declarations and Definitions
- More on Declarations and Definitions
- The Most Vexing Parse
- Finally, At Last
- Sound Bytes (Admittedly Off Topic)
- Local Classes
- Complex Arithmetic
- Floating Point Woes
- String Manipulation
- The Object Model
- The Object Model II
- The Object Model III
- Temporary Objects
- Temporary Objects: Advanced Techniques
- Over-Engineering
- Security Enhancements
- Drop the (automatic) Pilot
- Choosing the Right Container
- Choosing the Right Container II
- Choosing the Right Container, Part III
- Arrays and Pointers
- Low-Level File I/O
- Low-Level File I/O Part II
- static Declarations, Part I
- static Declarations, Part II
staticInitialization Order- Revisiting the Deprecation of File-Scope Static
- Virtual Memory and Memory Mapping
- Cellular Phone Programming Guidelines
- The Handle/Body Idiom
- Whole Program Optimization, Part I
- Whole Program Optimization, Part II
- Manipulating Directories
- Window Dressing
friendDeclarationsfriendPart II: the Interaction of Friendship and Template Classes- Forcing Object Allocation on Specific Storage Types
- Lazy Evaluation
- Cache and Carry
- Controlling a Container’s Capacity
- Non-Blocking I/O, Part I
- Non-Blocking I/O, Part II
- Using Unions for Automatic Conversion
- Launching a Child Process
- switch Statements
- Introducing the "struct Hack"
- Scoped Enumerators
- Doing Statistics with STL
- Fixing the "Unresolved External" Linkage Error
- Understanding Calling Conventions
- Understanding the Empty Base Optimization
- Implementing RPC with the door Library, Part 1
- Implementing RPC with the door Library, Part 2
- Eliminating Two Common Pointer and sizeof Bugs
- Command Line Arguments
- Performance Myths Busting
- Tag Names And Types Part I
- Tag Names And Types Part II
- The Infamous goto
- Trimming Strings
- Can Objects Live Forever? Part I
- Can Objects Live Forever? Part II
- A Tour of C99
- C++0X: The New Face of Standard C++
- C++0x Concurrency
- The Reflecting Circle New
- We Have Mail New
- The Soapbox
- Numeric Types and Arithmetic
- Careers
- Locales and Internationalization
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.


Account Sign In
View your cart