How to Use the opendir Function in C
-
Use the
opendir
Function to Open a Directory Stream -
Use the
readdir
Function to Iterate Over Directory Entries
This article will explain several methods of how to use the opendir
function in C.
Use the opendir
Function to Open a Directory Stream
The opendir
function is part of the POSIX specification and is defined in <dirent.h>
header file. The function takes a single char
pointer argument to specify the directory name to open. opendir
returns DIR*
structure or NULL
if an error is encountered. DIR
data type is implemented to represent directory stream, but the user should not allocate objects of the DIR
type. In the following example code, we take the directory name from the first command-line argument and pass the value to the opendir
function.
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "Usage: ./program directory_name\n");
exit(EXIT_FAILURE);
}
dp = opendir(argv[1]);
while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);
closedir(dp);
exit(EXIT_SUCCESS);
}
Use the readdir
Function to Iterate Over Directory Entries
Once the directory stream is open and we retrieved the valid DIR*
, we can read each entry in it using the readdir
function. Each call to readdir
function returns a pointer to dirent
structure representing the next directory entry. When the end of the directory stream is reached, readdir
returns NULL
. Thus, we implemented a simple while
loop that prints every entry in the opened directory stream. We modified code around opendir
and closedir
function calls to check for errors and output the corresponding message for debugging. It’s always good and secure practice to check if the library functions returned successfully.
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "Usage: ./program directory_name\n");
exit(EXIT_FAILURE);
}
errno = 0;
if ((dp = opendir(argv[1])) == NULL) {
switch (errno) {
case EACCES:
printf("Permission denied\n");
break;
case ENOENT:
printf("Directory does not exist\n");
break;
case ENOTDIR:
printf("'%s' is not a directory\n", argv[1]);
break;
}
exit(EXIT_FAILURE);
}
while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);
if (closedir(dp) == -1) perror("closedir");
exit(EXIT_SUCCESS);
}
Alternatively, we can add some error checking conditional statements for the readdir
function because the previous example may yield unclear output when the directory name is invalid or a different error occurred. The following code will additionally output the end-of-directory reached status after the successful iteration.
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "Usage: ./program directory_name\n");
exit(EXIT_FAILURE);
}
errno = 0;
if ((dp = opendir(argv[1])) == NULL) {
switch (errno) {
case EACCES:
printf("Permission denied\n");
break;
case ENOENT:
printf("Directory does not exist\n");
break;
case ENOTDIR:
printf("'%s' is not a directory\n", argv[1]);
break;
}
exit(EXIT_FAILURE);
}
errno = 0;
while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);
if (errno != 0) {
if (errno == EBADF)
printf("Invalid directory stream descriptor\n");
else
perror("readdir");
} else {
printf("End-of-directory reached\n");
}
if (closedir(dp) == -1) perror("closedir");
exit(EXIT_SUCCESS);
}
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook