原文地址:C語言中關於對目錄的操作
目錄的操作不論是在嵌入式產品還是應用軟件編程都是必不可少的,不同的開發語言可能略有不同,筆者主要是討論在Linux平台下對目錄的一系列操作:
1、獲取當前目錄操作:
在系統命令行下我們可以直接輸入命令:pwd 來獲取當前的工作目錄,但是你知道這個命令是怎么執行的嗎?它是由系統通過 Shell 程序來解釋執行的,在我們自己編寫程序的時候怎么能獲取當前的工作目錄呢?在標准C庫中提供了一系列關於目錄操作的接口函數:
char * getcwd(char * buf,size_t size);
getcwd函數把當前目錄的名字寫到給定的緩沖區buf里。如果目錄的名字超出了參數size給出的緩沖區長度(一個ERANGE錯誤),它就返回NULL。如果成功,它返回指針buf,我們可以訪問buf來獲取當前的目錄。可能當你獲取目錄后可能需要進入這個目錄或者跳到該目錄的父目錄,我們怎么操作呢?
2、 切換目錄:
int chdir(const char *path);
就像我們在shell里使用cd命令來切換目錄一樣,在程序里則可以使用chdir系統調用來實現目錄的變更,一般情況下是配合 Getcwd 函數一起使用來實現目錄定位操作。
3、 目錄的創建和刪除:
在系統命令行下我們可以通過 “ mkdir” , “ rmdir” 命令通過Shell來實現幫我們創建一個目錄和刪除一個目錄,如果在實際的產品開發中呢,總不可能我們自己去手動創建吧,很多情況下都是通過程序自動幫我們創建一個目錄來存放相應的文件。系統I/O庫中提供了下面相應的操作接口:
int mkdir(const char * path,mode_t mode);
mode的含義將按open系統調用的O_CREAT選項中的有關定義設置,當然,它還要服從umask的設置況。
int rmdir(const char *path);
4、 目錄掃描:
對目錄的掃描操作和文件的操作有點類似,都是通過對目錄結構體的操作,這個結構是系統維護的,一般情況下用戶不要去更改這個目錄結構體中的相應字段:
struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[256];
};
通過這個結構我們可以方便的實現文件的過濾,通過訪問結構體中的 “d_type” 和 “d_name” 變量可以非常方便的實現文件的查找,文件的訪問,文件的過濾。要實現一系列的目錄操作你總的先把這個目錄打開吧:
打開目錄:
DIR * opendir(const char *name)
函數返回一個目錄結構指針,所以在使用該函數時,我們需要顯示的定義相應的指針變量:
eg : DIR *dpt;
讀目錄操作:
struct dirent *readdir(DIR *dir);
函數實現目錄讀操作,將目錄流指針所指的目錄讀到相應的目錄結構中,函數返回該結構的指針,所以我們在使用該接口之前我們需要顯示的定於一個結構變量來接受函數的返回。
如: struct dirent *dir;
dir = readdir(DIR *dpt);
在我們對目錄的操作過程中你可能需要目錄指針卷繞操作,在C標准庫中也提供了相應的操作,和文件很相似吧 ,下面我們來看看:
void rewinddir(DIR *dir);
目錄掃描:
int scandir(const char *dir, struct dirent ***namelist,
int(*filter)(const struct dirent *),
int(*compar)(const struct dirent **, const struct dirent **));
int alphasort(const void *a, const void *b);
int versionsort(const void *a, const void *b);
咋一眼看到這個函數,復雜吧? 可能你在想我自己寫個目錄掃描小程序還簡單呢?后面我們將提供一個這樣小程序代碼,我們先看這個函數的使用吧:
參數: const char *dir ----------------------------------> 要掃描的目錄指針
struct dirent ***namelist ------------------------->要掃描的目錄結構
int(*filter)(const struct dirent *) -------------->要過濾的條件
int(*compar)(const struct dirent **, const struct dirent **));
----------------------------------> 掃描過程中要到的排序算法
下面是Linux系統自帶的一個使用例子可以幫我理解該函數的使用:
#include <dirent.h> int main(void) { struct dirent **namelist; int n; n = scandir(".", &namelist, 0, alphasort); if (n < 0) perror("scandir"); else { while(n--) { printf("%sn", namelist[n]->d_name); free(namelist[n]); } free(namelist); } return 0; } 例2: 自己實現一個目錄掃描操作: #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <stdlib.h> #define MAX_DIR_ENT 1024 typedef int(*qsort_compar)(const void *, const void *); int hxy_scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **)) { DIR * od; int n = 0; struct dirent ** list = NULL; struct dirent * ent ,* p; if((dir == NULL) || (namelist == NULL)) return -1; od = opendir(dir); if(od == NULL) return -1; list = (struct dirent **)malloc(MAX_DIR_ENT*sizeof(struct dirent *)); while(( ent = readdir(od)) != NULL) { if(filter!=NULL && !filter(ent)) continue; p = (struct dirent *)malloc(sizeof(struct dirent)); memcpy((void *)p,(void *)ent,sizeof(struct dirent)); list[n] = p; n++; if(n >= MAX_DIR_ENT) break; } closedir(od); *namelist = realloc((void *)list,n*sizeof(struct dirent *)); if(*namelist == NULL) *namelist = list; if(compar) qsort((void *)*namelist,n,sizeof(struct dirent *),(qsort_compar)compar); return n; } int filter_fn(const struct dirent * ent) { if(ent->d_type != DT_REG) return 0; return (strncmp(ent->d_name,"lib",3) == 0); } typedef int(*scandir_compar)(const struct dirent **, const struct dirent **); //第二個版本的掃描目錄程序, void scan_lib(const char * dir_name) { int n; struct dirent **namelist; n = hxy_scandir(dir_name, &namelist, filter_fn, (scandir_compar)alphasort); if (n < 0) perror("scandir"); else { while(n--) { printf("%sn", namelist[n]->d_name); free(namelist[n]); } free(namelist); } } int main(void) { scan_lib("/usr/lib"); return 0; } 例3: #include <sys/types.h> #include <dirent.h> #include <string.h> #include <stdio.h> int scan_file(char *dir_name) { DIR *dir; struct dirent *ent; char *ptr; dir = opendir(dir_name); if(dir == NULL) { fprintf(stderr,"open directory %s n",dir_name); return -1; } while( (ent = readdir(dir)) != NULL) { ptr = strrchr(ent->d_name,'.'); if(ptr && (strcasecmp(ent->d_name, ".txt") == 0)) printf("%sn", ent->d_name); } closedir(dir); } int main(void) { scan_file("/root/Desktop/C/src"); }
5、目錄關閉:
int closedir(DIR *dpt);
一些文件操作函數:http://blog.csdn.net/wh_19910525/article/details/13503221
http://blog.csdn.net/simmerlee/article/details/8281399