Quick links
Write a C program to list all files in a directory. How to list all files in a directory recursively. How to use readdir()
function to list all files in a directory recursively. Logic to list all files and sub-directories of a directory in C programming. How to use opendir()
, readdir()
and closedir()
library functions.
Required knowledge
Basic Input Output, File handling, Recursion
In programming while file manipulation, several times we come across a problem to list files in a directory. List files in a directory and recursively in its sub-directories. However, many C programmers don’t know how to get list of all files and directories within a directory. In this post I will explain how to list files and directories in a directory.
The readdir()
function
struct dirent *readdir(DIR *dirp);
function is defined in dirent.h
header file. It returns pointer to a structure dirent
type representing directory entry at the current position in directory stream dirp
. On every call to readdir()
method, it returns file/directory at current position in directory stream. readdir()
returns NULL
pointer if reached at the end of directory stream.
But wait, readdir(DIR *dirp)
function accepts a parameter of DIR
type. How to get reference to DIR
type.
The opendir()
function
DIR *opendir(const char *dirname);
is also defined in dirent.h
header file. Similar to file streams, opendir()
opens a directory stream corresponding to the file path pointed by dirname
. By default the opened directory stream points to first entry in the directory.
On success, the function returns a pointer to structure of DIR
type. Otherwise NULL
pointer. The returned value can be further used to perform operations on directory.
Similar to file stream, we open a directory stream, perform some action and finally close the stream. To close a directory stream we use closedir()
function.
The closedir()
function
int closedir(DIR *dirp);
is also present under same library file. It closes a directory pointed by dirp
pointer.
On success the function returns 0, otherwise -1.
How to list all files and directories of a directory
Step by step descriptive logic to list all files and directories in a directory.
- Input source path to list all files and sub-directories. Store it in some variable say
path
. - Open directory stream using
opendir()
and store its reference to*dir
ofDIR
type. - Initialize another variable of pointer to structure
dirent
type, saystruct dirent *dp
. - Read next element from directory stream using
dp = readdir(dir)
. - Print current directory stream item name, using
dp->name
. - Repeat step 4-5 till
dp != NULL
. - Finally, close the directory stream pointed by
dir
variable.
Program to list all files and sub-directories in a directory
/**
* C program to list all files and sub-directories in a directory.
*/
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
void listFiles(const char *path);
int main()
{
// Directory path to list files
char path[100];
// Input path from user
printf("Enter path to list files: ");
scanf("%s", path);
listFiles(path);
return 0;
}
/**
* Lists all files and sub-directories at given path.
*/
void listFiles(const char *path)
{
struct dirent *dp;
DIR *dir = opendir(path);
// Unable to open directory stream
if (!dir)
return;
while ((dp = readdir(dir)) != NULL)
{
printf("%s\n", dp->d_name);
}
// Close directory stream
closedir(dir);
}
You can easily convert above function to work for recursive directory listing. Check below program if facing difficulties implementing it recursive way.
Program to list all files and sub-directories of a directory recursively
/**
* C program to list contents of a directory recursively.
*/
#include <stdio.h>
#include <string.h>
void listFilesRecursively(char *path);
int main()
{
// Directory path to list files
char path[100];
// Input path from user
printf("Enter path to list files: ");
scanf("%s", path);
listFilesRecursively(path);
return 0;
}
/**
* Lists all files and sub-directories recursively
* considering path as base path.
*/
void listFilesRecursively(char *basePath)
{
char path[1000];
struct dirent *dp;
DIR *dir = opendir(basePath);
// Unable to open directory stream
if (!dir)
return;
while ((dp = readdir(dir)) != NULL)
{
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
{
printf("%s\n", dp->d_name);
// Construct new path from our base path
strcpy(path, basePath);
strcat(path, "/");
strcat(path, dp->d_name);
listFilesRecursively(path);
}
}
closedir(dir);
}}
Enter path to list files: . .git COMMIT_EDITMSG config description FETCH_HEAD HEAD hooks pack ORIG_HEAD packed-refs refs heads master remotes origin HEAD master tags .gitignore .vscode c_cpp_properties.json bin a.exe c-program-to-find-maximum-and-minimum-range-of-data-types-using-macro.c c-programming-ws.code-workspace data append.txt blanks.txt compare1.txt compare2.txt copy-file.txt empty-lines.txt even-numbers.txt file1.txt file2.txt file3.txt file4.txt merged-file.txt numbers.txt odd-numbers.txt prime-numbers.txt LICENSE README.md src file append-data.c check-file-properties.c compare-file.c copy-file-contents.c copy-file-using-function.c count-characters-words-lines-in-file.c count-occurrences-of-all-words-in-file.c create-and-write-contents-to-file.c delete-all-blank-lines.c delete-specific-line.c delete-word-from-file.c directory-exists.c file-exists.c file-programming-example-list.md find-word-in-file.c list-files.c merge-file.c print-source-of-current-file.c read-from-file-using-fgetc.c read-from-file-using-fgets.c read-numbers-write-even-odd-prime-to-separate-file.c remove-empty-lines.c rename-file.c replace-line-in-file.c replace-word-in-file.c replace-word.c toggle-case-of-file-contents.c stdlib atof.c atoi.c atol.c atoll.c strtol.c strtoll.c strtoul.c strtoull.c
Let’s raise the level. The above recursive method prints all files and sub-directories in same indentation. Its very difficult to know which files are in which directory. So lets print all files and sub-directories in tree structure.
Program to print all files and sub-directories in tree structure
/**
* C program to list file and sub-directories of a directory
* recursively in tree structure.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
void tree(char *basePath, const int root);
int main()
{
// Directory path to list files
char path[100];
// Input path from user
printf("Enter path to list files: ");
scanf("%s", path);
tree(path, 0);
return 0;
}
/**
* Tree, prints all files and sub-directories of a given
* directory in tree structure.
*
* @param basePath Base path to traverse directory
* @param root Integer representing indention for current directory
*/
void tree(char *basePath, const int root)
{
int i;
char path[1000];
struct dirent *dp;
DIR *dir = opendir(basePath);
if (!dir)
return;
while ((dp = readdir(dir)) != NULL)
{
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
{
for (i=0; i<root; i++)
{
if (i%2 == 0 || i == 0)
printf("%c", 179);
else
printf(" ");
}
printf("%c%c%s\n", 195, 196, dp->d_name);
strcpy(path, basePath);
strcat(path, "/");
strcat(path, dp->d_name);
tree(path, root + 2);
}
}
closedir(dir);
}
Enter path to list files: . ├─.git │ ├─COMMIT_EDITMSG │ ├─config │ ├─description │ ├─FETCH_HEAD │ ├─HEAD │ ├─ORIG_HEAD │ ├─packed-refs │ ├─refs │ │ ├─heads │ │ │ ├─master │ │ ├─remotes │ │ │ ├─origin │ │ │ │ ├─HEAD │ │ │ │ ├─master │ │ ├─tags ├─.gitignore ├─.vscode │ ├─c_cpp_properties.json ├─bin │ ├─a.exe ├─c-program-to-find-maximum-and-minimum-range-of-data-types-using-macro.c ├─c-programming-ws.code-workspace ├─data │ ├─append.txt │ ├─blanks.txt │ ├─compare1.txt │ ├─compare2.txt │ ├─copy-file.txt │ ├─empty-lines.txt │ ├─even-numbers.txt │ ├─file1.txt │ ├─file2.txt │ ├─file3.txt │ ├─file4.txt │ ├─merged-file.txt │ ├─numbers.txt │ ├─odd-numbers.txt │ ├─prime-numbers.txt ├─LICENSE ├─README.md ├─src │ ├─file │ │ ├─append-data.c │ │ ├─check-file-properties.c │ │ ├─compare-file.c │ │ ├─copy-file-contents.c │ │ ├─copy-file-using-function.c │ │ ├─count-characters-words-lines-in-file.c │ │ ├─count-occurrences-of-all-words-in-file.c │ │ ├─create-and-write-contents-to-file.c │ │ ├─delete-all-blank-lines.c │ │ ├─delete-specific-line.c │ │ ├─delete-word-from-file.c │ │ ├─directory-exists.c │ │ ├─file-exists.c │ │ ├─file-programming-example-list.md │ │ ├─find-word-in-file.c │ │ ├─list-files.c │ │ ├─merge-file.c │ │ ├─print-source-of-current-file.c │ │ ├─read-from-file-using-fgetc.c │ │ ├─read-from-file-using-fgets.c │ │ ├─read-numbers-write-even-odd-prime-to-separate-file.c │ │ ├─remove-empty-lines.c │ │ ├─rename-file.c │ │ ├─replace-line-in-file.c │ │ ├─replace-word-in-file.c │ │ ├─replace-word.c │ │ ├─toggle-case-of-file-contents.c │ ├─stdlib │ │ ├─atof.c │ │ ├─atoi.c │ │ ├─atol.c │ │ ├─atoll.c │ │ ├─strtol.c │ │ ├─strtoll.c │ │ ├─strtoul.c │ │ ├─strtoull.c
Happy coding 😉