opendir 函數(shù)本身無(wú)法實(shí)現(xiàn)遞歸目錄遍歷,需要結(jié)合 readdir、closedir 和 stat (或 lstat 避免符號(hào)鏈接問(wèn)題) 函數(shù),并使用遞歸調(diào)用來(lái)實(shí)現(xiàn)。以下是一個(gè)改進(jìn)的 C 語(yǔ)言示例,它能夠更穩(wěn)健地處理目錄遍歷,包括符號(hào)鏈接:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/stat.h> #include <limits.h> // for PATH_MAX void list_directory_contents(const char *path) { DIR *dir; struct dirent *entry; struct stat path_stat; char full_path[PATH_MAX]; dir = opendir(path); if (!dir) { perror("opendir"); return; } while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } // 使用 snprintf 避免緩沖區(qū)溢出 if (snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name) >= sizeof(full_path)) { fprintf(stderr, "Path too long: %s/%s ", path, entry->d_name); continue; } if (lstat(full_path, &path_stat) == -1) { // 使用 lstat 處理符號(hào)鏈接 perror("lstat"); continue; } if (S_ISDIR(path_stat.st_mode)) { list_directory_contents(full_path); } else if (S_ISREG(path_stat.st_mode)) { // 只打印常規(guī)文件 printf("%s ", full_path); } else if (S_ISLNK(path_stat.st_mode)) { printf("Symbolic link: %s ", full_path); // 處理符號(hào)鏈接 } else { printf("Other file type: %s ", full_path); // 處理其他文件類型 } } closedir(dir); } int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "Usage: %s <directory> ", argv[0]); return EXIT_FAILURE; } list_directory_contents(argv[1]); return EXIT_SUCCESS; }
此版本改進(jìn)之處:
- 錯(cuò)誤處理: 更全面的錯(cuò)誤處理,包括 opendir 和 lstat 的錯(cuò)誤檢查。
- 路徑長(zhǎng)度限制: 使用 snprintf 來(lái)防止?jié)撛诘木彌_區(qū)溢出,避免路徑過(guò)長(zhǎng)導(dǎo)致程序崩潰。
- 符號(hào)鏈接處理: 使用 lstat 代替 stat,可以正確處理符號(hào)鏈接,避免無(wú)限遞歸。
- 文件類型區(qū)分: 區(qū)分常規(guī)文件和其他文件類型,例如符號(hào)鏈接,提供更詳細(xì)的信息。
這個(gè)程序仍然假設(shè) PATH_MAX 是定義的,在某些系統(tǒng)中可能需要包含額外的頭文件或使用其他方法來(lái)獲取最大路徑長(zhǎng)度。 記住編譯時(shí)需要鏈接 -lm (如果你的系統(tǒng)需要)。 例如:gcc your_file.c -o your_program -lm