首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux C/C++ 遞迴遍歷目錄完整指南:opendir/readdir、scandir、nftw、std::filesystem

     編輯:關於C語言

方法一:POSIX 基礎 API (dirent.h)

簡易版:單層列舉

#include <dirent.h>
#include <stdio.h>

int main(void) {
    DIR *dp = opendir("/");
    if (!dp) { perror("opendir"); return 1; }
    struct dirent *ep;
    while ((ep = readdir(dp))) {
        if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) continue;
        printf("type=%d, name=%s\n", ep->d_type, ep->d_name);
    }
    closedir(dp);
    return 0;
}

遞迴版:完整路徑遍歷

#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void walk(const char *path) {
    struct dirent **list;
    int n = scandir(path, &list, NULL, alphasort);
    if (n < 0) { perror("scandir"); return; }

    for (int i = 0; i < n; ++i) {
        if (strcmp(list[i]->d_name, ".") == 0 || strcmp(list[i]->d_name, "..") == 0) {
            free(list[i]); continue;
        }
        char full[PATH_MAX];
        snprintf(full, sizeof(full), "%s/%s", path, list[i]->d_name);
        puts(full);

        if (list[i]->d_type == DT_DIR) // 是目錄
            walk(full); // 遞迴
        free(list[i]);
    }
    free(list);
}

int main(void) { walk("/home/user"); return 0; }

方法二:nftw() (File Tree Walk) — 更健壯

#include <ftw.h>
#include <stdio.h>

int callback(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) {
    printf("%*s%s\n", ftwbuf->level * 2, "", fpath);
    return 0; // 繼續遍歷
}

int main(void) {
    nftw("/home/user", callback, 20, FTW_PHYS); // 20 = 最大開啟檔案描述符數
    return 0;
}

優點:自動處理符號連結循環 (FTW_PHYS)、深度優先/廣度優先可控、標準化錯誤處理。

方法三:C++17 std::filesystem (現代、跨平台)

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
    for (auto &entry : fs::recursive_directory_iterator("/home/user")) {
        std::cout << entry.path() << '\n';
    }
    return 0;
}

支援 Windows/Linux/macOS,自動處理編碼、權限錯誤、迴路偵測。

方法四:Qt QDirIterator (專案已用 Qt 時)

QDirIterator it("/home/user", QDir::AllEntries | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while (it.hasNext()) {
    qDebug() << it.next();
}

Shell 一行指令

# 完整路徑
find /home/user -type f

# 僅檔名
ls -R /home/user

關鍵比較表

方法標準遞迴支援符號連結處理錯誤處理適用場景
opendir/readdirPOSIX手寫遞迴需自行檢查手動教學、極簡環境
scandirPOSIX手寫遞迴需自行檢查手動需排序、過濾
nftwPOSIX.1-2008內建FTW_PHYS/FTW_DEPTH回呼回傳值控制系統程式、備份工具
std::filesystemC++17內建自動偵測迴路例外機制現代 C++ 專案
Qt QDirIteratorQt內建自動信號/槽Qt 專案

實務建議

  • 生產環境優先 nftw 或 std::filesystem,健壯度最高
  • 避免對 /proc, /sys, /dev 等虛擬檔案系統深度遍歷(可能掛住)
  • 大量檔案時注意檔案描述符耗盡,nftw 可限制並發
  • 跨平台專案統一用 std::filesystem,CMake 需 set(CMAKE_CXX_STANDARD 17)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved