In Linux system programming, it is often necessary to traverse the directory to obtain all the files and subdirectories in the directory. Traversing directories recursively is a common method that can be implemented using the C language. This blog will introduce in detail how to use C language to implement the process of recursively traversing directories, provide corresponding code examples, and explain the use of related functions.
Article Directory
1. Introduction of related functions
1.1 opendir()
1.1.1 Function prototype, parameters and return value
opendir
The function is used to open a directory and return a DIR
pointer to the type, which is used for subsequent directory operations.
prototype:
DIR *opendir(const char *path);
parameter:
path
: Path to the directory to open.
return value:
DIR
Return value: If the directory is successfully opened, a pointer to the type is returned ; if it fails, it is returnedNULL
.
1.1.2 Function Example
Here is an example of using opendir
a function to open a directory:
#include <stdio.h>
#include <dirent.h>
int main() {
const char *path = "/path/to/directory";
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
// 目录操作...
closedir(dir);
return 0;
}
1.1.3 Code Explanation
In the above example, we first defined the directory path to open path
, then used opendir
the function to open the directory and stored the returned pointer in dir
a variable. Then, we can perform some directory operations, such as using readdir
functions to read files in the directory. Finally, we use closedir
the function to close the directory.
If opendir
the function fails, it returns NULL
and stores the error message in a global variable errno
. We can use perror
the function to print out error messages for debugging and troubleshooting
It should be noted that after using DIR
the pointer of the type, you must remember to use closedir
the function to close the directory to release related resources.
1.2 readdir()
1.2.1 Function prototype, parameter, return value and structure definition
readdir
The function is used to read the files in the directory and returns a dirent
pointer to the structure.
prototype:
struct dirent *readdir(DIR *dir);
parameter:
dir
: A pointer to the opened directory.
return value:
- Return value: If the next file is successfully read,
dirent
a pointer to the structure is returned; if the end of the directory is reached or an error occurs, it is returnedNULL
.
dirent
The structure is defined as follows:
struct dirent {
ino_t d_ino; // 文件的inode号
off_t d_off; // 文件在目录中的偏移量
unsigned short d_reclen; // 文件名的长度
unsigned char d_type; // 文件的类型
char d_name[256]; // 文件名
};
1.2.2 Function example
Here's an readdir
example of using a function to read a file in a directory:
#include <stdio.h>
#include <dirent.h>
int main() {
const char *path = "/path/to/directory";
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
return 0;
}
1.2.3 Code Explanation
In the above example, we first use opendir
the function to open the directory and store the returned pointer in dir
a variable. Then, we use a loop to read each file in the directory. readdir
The function will return a dirent
pointer to the structure, we can d_name
get the file name by accessing the members, and perform corresponding operations. In the example we simply use printf
the function to print out the filename. Finally, we use closedir
the function to close the directory.
It should be noted that when readdir
the function returns NULL
, it means that the end of the directory has been read, or an error has occurred. Therefore, we can NULL
determine whether to continue reading the files in the directory by judging whether the return value is .
1.3 closedir()
1.3.1 Function prototype, parameters and return value
closedir
The function is used to close the directory opened by the function before opendir
and release related resources.
prototype:
int closedir(DIR *dir);
parameter:
dir
: A pointer to the opened directory.
return value:
- Return Value: 0 if the directory was successfully closed, or -1 if an error occurred.
1.3.2 Function example
Here's an example of using closedir
a function to close a directory:
#include <stdio.h>
#include <dirent.h>
int main() {
const char *path = "/path/to/directory";
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
// 目录操作...
if (closedir(dir) == -1) {
perror("closedir");
return -1;
}
return 0;
}
1.3.3 Code Explanation
In the above example, we first use opendir
the function to open the directory and store the returned pointer in dir
a variable. Next, we can do some directory manipulation. Finally, we use closedir
the function to close the directory and check if the return value is -1 to see if an error occurred.
It should be noted that closedir
the function will release resources related to the directory, so after using the directory, you must remember to call the closedir
function to close the directory.
1.4 snprintf()
1.4.1 Function prototype, parameters and return value
snprintf
function is a safe string formatting function for outputting formatted data into a string.
prototype:
int snprintf(char *str, size_t size, const char *format, ...);
parameter:
str
: Pointer to the string used to store the formatted result.size
: The size of the string storing the formatted result.format
: format string, specify the output format.
return value:
- Return Value: Returns the number of characters written to the string (not including the terminator) on success, or a negative value on failure.
snprintf
function works printf
like a function, but it stores the formatted result into the specified string instead of outputting it to standard output.
1.4.2 Function example
Here is an snprintf
example using the function:
#include <stdio.h>
int main() {
char buffer[100];
int num = 42;
const char *str = "Hello, world!";
int len = snprintf(buffer, sizeof(buffer), "Number: %d, String: %s", num, str);
if (len >= sizeof(buffer)) {
printf("Buffer is too small\n");
return -1;
}
printf("Formatted string: %s\n", buffer);
return 0;
}
1.4.3 Code Explanation
In the above example, we first define a character array of size 100 buffer
to store the formatted result. Then, we define an integer variable num
and a string variable str
to be passed to the format string. Next, we use snprintf
the function to store the formatted result into buffer
and output it to standard output. Finally, we check len
whether the return value exceeds buffer
the size of to see if the buffer is large enough to hold the formatted result.
It should be noted that snprintf
the function will format according to the specified format string and parameters, and store the result in the specified string. It ensures that the formatted result does not exceed the specified size and automatically truncates the string if necessary. Therefore, using snprintf
functions can avoid the problem of buffer overflow.
1.5 strcmp()
1.5.1 Function prototype, parameters and return value
strcmp
Function to compare two strings for equality.
prototype:
int strcmp(const char *s1, const char *s2);
parameter:
s1
: The first string to compare.s2
: The second string to compare.
return value:
- Return Value: Returns 0 if the two strings are equal; returns a negative number if the first string is less than the second; returns a positive number if the first string is greater than the second .
strcmp
The function compares the two strings character by character, lexicographically, until either an unequal character is found or the end of the string is encountered\0
. Returns 0 if the two strings are equal; returns a negative number if the first string comes lexicographically before the second; returns a negative number if the first string comes lexicographically second After the string, a positive number is returned.
1.5.2 Function example
Here's an strcmp
example that uses a function to compare two strings:
#include <stdio.h>
#include <string.h>
int main() {
const char *s1 = "Hello";
const char *s2 = "World";
int result = strcmp(s1, s2);
if (result == 0) {
printf("The strings are equal\n");
} else if (result < 0) {
printf("The first string is less than the second string\n");
} else {
printf("The first string is greater than the second string\n");
}
return 0;
}
1.5.3 Code Explanation
In the above example, we defined two strings s1
and s2
then used strcmp
the function to compare them. Depending on the return value, we output the corresponding result.
It should be noted that strcmp
the function compares the contents of the strings, not the addresses of the strings. Therefore, even if the addresses of the two strings are different, as long as their contents are the same, strcmp
the function will return 0. Also, strcmp
functions are case-sensitive, and if you want case-insensitive comparisons, you can use strcasecmp
functions.
2. Recursive traversal directory implementation
2.1 Sample code:
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
void traverse_directory(const char *path) {
DIR *dir;
struct dirent *entry;
struct stat file_stat;
// 打开目录
dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return;
}
// 读取目录中的每个文件
while ((entry = readdir(dir)) != NULL) {
// 构建文件的完整路径
char file_path[1024];
snprintf(file_path, sizeof(file_path), "%s/%s", path, entry->d_name);
// 获取文件的信息
if (lstat(file_path, &file_stat) < 0) {
perror("lstat");
continue;
}
// 判断文件类型
if (S_ISDIR(file_stat.st_mode)) {
// 如果是目录,则递归遍历
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
traverse_directory(file_path);
} else {
// 如果是文件,则打印文件名
printf("%s\n", file_path);
}
}
// 关闭目录
closedir(dir);
}
int main(int argc,char *argv[]) {
traverse_directory(argv[]);
return 0;
}
2.2 Code explanation
In the above code, we defined a traverse_directory
function to traverse directories recursively. This function takes a path as an argument, first opens the directory, and then reads each file in the directory. For each file, we first build the full path to the file, then use lstat
a function to get the file's information. If the file is a directory, the function is called recursively traverse_directory
; if the file is a regular file, the filename is printed. Finally, we close the directory.
In main
the function, we specify the directory path to traverse and call traverse_directory
the function to traverse.
dirent.h
It should be noted that in the above code, header files are used sys/stat.h
to operate directories and files, and stdio.h
header string.h
files are used to perform string operations. Also, functions are used in the code lstat
to get information about files instead of stat
functions because lstat
functions can handle symbolic links.