參考《UNIX 環境高級編程》課後題 4.11,採用 進入子目錄 → 讀取 → 遞歸 → 返回父目錄 策略,避免拼接完整路徑,顯著提升性能。
chdir(fullpath) 進入目標目錄。opendir(".") 打開當前目錄,readdir 讀取條目。. 和 ..。lstat 獲取類型,更新計數器;若為目錄,遞歸 dopath。chdir("..") 回退。static int dopath(MyFunc *func) {
struct stat statbuf;
DIR *dp; struct dirent *dirp;
if (lstat(fullpath, &statbuf) < 0) return func(fullpath, &statbuf, FTW_NS);
if (!S_ISDIR(statbuf.st_mode)) return func(fullpath, &statbuf, FTW_F);
if (func(fullpath, &statbuf, FTW_D) != 0) return -1;
if (chdir(fullpath) < 0) return -1;
if (!(dp = opendir("."))) return func(fullpath, &statbuf, FTW_ND);
while ((dirp = readdir(dp))) {
if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, "..")) continue;
strcpy(fullpath, dirp->d_name);
if (dopath(func) != 0) break;
}
chdir("..");
closedir(dp);
return 0;
}
static long sock_c, lnk_c, reg_c, blk_c, dir_c, chr_c, fifo_c, total_c;
static int myfunc(const char *path, const struct stat *st, int type) {
switch (type) {
case FTW_F:
switch (st->st_mode & S_IFMT) {
case S_IFSOCK: sock_c++; break;
case S_IFLNK: lnk_c++; break;
case S_IFREG: reg_c++; break;
case S_IFBLK: blk_c++; break;
case S_IFCHR: chr_c++; break;
case S_IFIFO: fifo_c++; break;
}
break;
case FTW_D: dir_c++; break;
// FTW_NS, FTW_ND 錯誤處理...
}
return 0;
}


stat 系統調用少,速度提升明顯(圖中 descend_hierarchy_ch 更快)。stat 開銷大。strlen/strcpy 開銷。fullpath 復用單一緩衝區,無頻繁 malloc/free。此模式適用於深度遍歷、大量文件場景,是 Linux 系統編程中目錄遍歷的高效範式。