[Linux/C++] 用 readdir() 尋訪某目錄下所有的子目錄與檔案

[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,759 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料