[Linux/C++] 用 readdir() 尋訪某目錄下所有的子目錄與檔案
今天在寫一個測試程式,要尋訪特定目錄下所有的子目錄與檔案,
在 Linux 下要實現這個程式,就是要用到 opendir, readdir, 和 closedir 這幾個函式,
簡單寫個測試程式吧~
假設在 main() 裡面,呼叫一個 VisitDir() 的函式,
只要給一個目錄的路徑,就會開始往下尋訪:
#include <dirent.h> #include <stdio.h> #include <string> #include <string.h> #include <sys/stat.h> int main(int argc, char* argv[]) { if (argc >= 2) { VisitDir(argv[1]); } return 0; }
VisitDir() 的尋訪方式是先用 opendir() 開啟目錄,
接著用 readdir() 將其下的每個檔案/目錄讀出來,再交給 VisitItem() 來處理~
最後記得要用 closedir() 關閉這一層目錄:
void VisitDir(const char* szDir) { // Open folder DIR* pDir = opendir(szDir); if (pDir != NULL) { // Read items inside the folder struct dirent* pEntry = NULL; while ((pEntry = readdir(pDir)) != NULL) { VisitDirItem(szDir, pEntry); } } // Close folder closedir(pDir); }
VisitDirItem() 則是先忽略 . 和 .. 這兩個特殊的目錄 (避免無窮迴圈),
這邊 dirent 結構中的 d_name 只包含了檔案名稱,想要完整的路徑的話得自己串接起來。
接著用 lstat() 查詢一下檔案的狀態,
可能有人會想說為什麼不用 dirent 結構裡就有的 d_type 來判斷檔案型態,
這是因為 d_type 並不是所有的檔案系統都會支援,
像我看 CentOS 上的 xfs filesystem,目錄和檔案都會是相同的值…
因此只好自己用 lstat() 來查詢了:
void VisitDirItem(const char* szDir, struct dirent* pEntry) { // Ignore . and .. if (strcmp(pEntry->d_name, ".") != 0 && strcmp(pEntry->d_name, "..") != 0) { char szPath[1024] = {}; int nLen = snprintf(szPath, sizeof(szPath)-1, "%s/%s", szDir, pEntry->d_name); szPath[nLen] = '\0'; // Query file status struct stat st = {}; lstat(szPath, &st); if (S_ISDIR(st.st_mode)) { VisitDir(szPath); } else if (S_ISREG(st.st_mode)) { printf("Scanning %s...\n", szPath); } } }
用完 lstat() 查到檔案狀態後,就可以用 S_ISDIR(), S_ISREG() 等巨集,
來查看這個是一個目錄,還是一個一般的檔案 (還有很多種像 S_ISBLK, S_ISFIFO)~
若是一個目錄的話,就可以再呼叫 VisitDir() 來遞迴處理子目錄,
若是一般檔案的話,就可以作想對檔案處理的動作了 (本例中就只是印一行檔案的路徑)~
(本頁面已被瀏覽過 4,747 次)