[Linux operating system] Linux system programming realizes recursive traversal of directories, and explains in detail the use of opendir, readdir, closedir, snprintf, strcmp and other functions

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.
insert image description here

1. Introduction of related functions

1.1 opendir()

1.1.1 Function prototype, parameters and return value

opendirThe function is used to open a directory and return a DIRpointer 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:

  • DIRReturn value: If the directory is successfully opened, a pointer to the type is returned ; if it fails, it is returned NULL.

1.1.2 Function Example

Here is an example of using opendira 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 opendirthe function to open the directory and stored the returned pointer in dira variable. Then, we can perform some directory operations, such as using readdirfunctions to read files in the directory. Finally, we use closedirthe function to close the directory.

If opendirthe function fails, it returns NULLand stores the error message in a global variable errno. We can use perrorthe function to print out error messages for debugging and troubleshooting

It should be noted that after using DIRthe pointer of the type, you must remember to use closedirthe function to close the directory to release related resources.



1.2 readdir()

1.2.1 Function prototype, parameter, return value and structure definition

readdirThe function is used to read the files in the directory and returns a direntpointer 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, direnta pointer to the structure is returned; if the end of the directory is reached or an error occurs, it is returned NULL.

direntThe 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 readdirexample 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 opendirthe function to open the directory and store the returned pointer in dira variable. Then, we use a loop to read each file in the directory. readdirThe function will return a direntpointer to the structure, we can d_nameget the file name by accessing the members, and perform corresponding operations. In the example we simply use printfthe function to print out the filename. Finally, we use closedirthe function to close the directory.

It should be noted that when readdirthe function returns NULL, it means that the end of the directory has been read, or an error has occurred. Therefore, we can NULLdetermine 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

closedirThe function is used to close the directory opened by the function before opendirand 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 closedira 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 opendirthe function to open the directory and store the returned pointer in dira variable. Next, we can do some directory manipulation. Finally, we use closedirthe function to close the directory and check if the return value is -1 to see if an error occurred.

It should be noted that closedirthe function will release resources related to the directory, so after using the directory, you must remember to call the closedirfunction to close the directory.



1.4 snprintf()

1.4.1 Function prototype, parameters and return value

snprintffunction 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.

snprintffunction works printflike 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 snprintfexample 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 bufferto store the formatted result. Then, we define an integer variable numand a string variable strto be passed to the format string. Next, we use snprintfthe function to store the formatted result into bufferand output it to standard output. Finally, we check lenwhether the return value exceeds bufferthe size of to see if the buffer is large enough to hold the formatted result.

It should be noted that snprintfthe 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 snprintffunctions can avoid the problem of buffer overflow.



1.5 strcmp()

1.5.1 Function prototype, parameters and return value

strcmpFunction 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 .

strcmpThe 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 strcmpexample 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 s1and s2then used strcmpthe function to compare them. Depending on the return value, we output the corresponding result.

It should be noted that strcmpthe 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, strcmpthe function will return 0. Also, strcmpfunctions are case-sensitive, and if you want case-insensitive comparisons, you can use strcasecmpfunctions.



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_directoryfunction 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 lstata 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 mainthe function, we specify the directory path to traverse and call traverse_directorythe function to traverse.

dirent.hIt should be noted that in the above code, header files are used sys/stat.hto operate directories and files, and stdio.hheader string.hfiles are used to perform string operations. Also, functions are used in the code lstatto get information about files instead of statfunctions because lstatfunctions can handle symbolic links.

Guess you like

Origin blog.csdn.net/Goforyouqp/article/details/132232262