掃描dir目錄函式之scandir()
scandir: 讀取特定的目錄資料標頭檔案: dirent.h 函式定義: int scandir(const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), int (*compar)(const struct dirent**, const struct dirent**));
說明: scandir()會掃描引數dir指定的目錄檔案, 經由引數select指定的函式來挑選目錄結構至引數 namelist陣列中, 最後在呼叫引數compar指定的函式來排序namelist陣列中的目錄資料. 每次從目錄檔案中讀取一個目錄結構後便將此結構傳給引數select所指的函式, select函式若不想要將此目錄機構複製到 namelist陣列就返回0, 若select為空指標則代表選擇所有的目錄結構. scandir()會呼叫qsort()來排序資料, 引數compar則為qsort()的引數, 若是要排列目錄名稱字母則可使用alphasort(). 結構dirent定義請參考readdir(). 成功則返回複製到namelist陣列中的資料結構數目, 有錯誤發生則返回-1. ENOMEM表示核心記憶體不足.
其中 dirent原型為:
struct linux_dirent64 {
u64 d_ino;
s64 d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[0];
};
測試一下該函式功能,新建一個資料夾“test”在裡面建若干檔案和資料夾 如圖:
編寫測試程式碼:
#include <dirent.h> int main(void) { struct dirent **namelist; int n; n = scandir(".", &namelist, NULL, alphasort); if (n < 0) perror("scandir"); else { while (n--) { printf("%s:%d\n", namelist[n]->d_name,namelist[n]->d_type); free(namelist[n]); } free(namelist); } }
執行發現:
F5:0
F4:0
F3:0
F2:0
F1:0
D4:0
D3:0
D2:0
D1:0
..:0
.:0
說明namelist[n]->d_type對檔案型別支援還是不夠的,需要用stat函式繼續對其分析。
完整測試程式碼如下:
struct dirent **namelist; struct stat tStat; int n; char strTmp[256]; n = scandir("/prj/test/", &namelist, NULL, alphasort); if (n < 0) perror("scandir"); else { while (n--) { snprintf(strTmp, 256, "%s/%s", "/prj/test/", namelist[n]->d_name); strTmp[255] = '\0'; if ((stat(strTmp, &tStat) == 0)) { if(S_ISDIR(tStat.st_mode)) { printf("%s:is a dir\n", namelist[n]->d_name); } else if(S_ISREG(tStat.st_mode)) { printf("%s:is a file\n", namelist[n]->d_name); } else { printf("%s:unknow2\n", namelist[n]->d_name); } } free(namelist[n]); } free(namelist); }
此時列印資訊為:
F5:is a file
F4:is a file
F3:is a file
F2:is a file
F1:is a file
D4:is a dir
D3:is a dir
D2:is a dir
D1:is a dir
..:is a dir
.:is a dir
將該目錄下的檔案及目錄都識別出來了