使用 POSIX dirent.h 介面,遞迴掃描指定目錄下的所有子目錄與一般檔案,並統計總數。支援任意深度目錄樹,動態分配路徑緩衝區。
#define MAX_PATH_LENGTH 512
#define MAX_FILE_EXTENSION 9
unsigned long visit_dirs = 0;
unsigned long visit_files = 0;
listdirvoid listdir(char *path) {
DIR *ptr_dir;
struct dirent *dir_entry;
char *child_path = malloc(MAX_PATH_LENGTH);
char *file_path = malloc(MAX_PATH_LENGTH);
// ... 錯誤檢查與初始化 ...
ptr_dir = opendir(path);
while ((dir_entry = readdir(ptr_dir)) != NULL) {
// 目錄項目:略過 . 和 ..
if (dir_entry->d_type & DT_DIR) {
if (strcmp(dir_entry->d_name, ".") == 0 || strcmp(dir_entry->d_name, "..") == 0) continue;
sprintf(child_path, "%s/%s", path, dir_entry->d_name);
printf("[DIR]%s\n", child_path);
visit_dirs++;
listdir(child_path); // 遞迴
}
// 一般檔案
if (dir_entry->d_type & DT_REG) {
sprintf(file_path, "%s/%s", path, dir_entry->d_name);
printf("[FILE]%s\n", file_path);
visit_files++;
}
}
free(child_path);
free(file_path);
}
DT_DIR、DT_REG 快速區分類型,免去額外 stat() 系統呼叫 (視檔案系統支援度)。sprintf 組合完整路徑,注意緩衝區大小邊界。int main(int argc, char* argv[]) {
if (argc == 2) {
listdir(argv[1]);
printf("Total DIR: %ld, Total FILE: %ld\n", visit_dirs, visit_files);
} else {
printf("Usage: listdir <dir>\n");
}
return 0;
}
gcc listdir.c -o listdir
./listdir /path/to/scan
fts(3) 或 nftw(3) 更健壯的樹遍歷 API。DT_LNK) 處理,避免循環掛載導致無限遞迴。MAX_FILE_EXTENSION 預留)。errno 碼,提供更友善訊息。