學習貴在堅持,兜兜轉轉,發現仍是從基礎作起吧,打好基礎,纔會長期的堅持下去。。。node
第一個練習:shell命令 「ls"的實現與遞歸shell
一、簡介:ls 的做用是列舉當前目錄下全部的目錄和文件。ide
二、用到的結構體——struct dirent;函數
1 struct dirent 2 { 3 long d_ino; /* inode number 索引節點號 */ 4 off_t d_off; /* offset to this dirent 在目錄文件中的偏移 */ 5 unsigned short d_reclen; /* length of this d_name 文件名長 */ 6 unsigned char d_type; /* the type of d_name 文件類型 */ 7 char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最長255字符 */ 8 }
struct dirent 結構體中成員d_type文件類型的分類:學習
1 enum 2 { 3 DT_UNKNOWN = 0, //類型未知。少數文件系統會出現此函數不支持的文件類型,另外一些則老是返回這個值。譯者注:總之這個值是爲了應對不兼容的文件系統而設置的; 4 # define DT_UNKNOWN DT_UNKNOWN 5 DT_FIFO = 1, // 一個命名管道,或FIFO 6 # define DT_FIFO DT_FIFO 7 DT_CHR = 2, // 字符設備 8 # define DT_CHR DT_CHR 9 DT_DIR = 4, // 目錄 10 # define DT_DIR DT_DIR 11 DT_BLK = 6, // 塊設備 12 # define DT_BLK DT_BLK 13 DT_REG = 8, // 常規文件 14 # define DT_REG DT_REG 15 DT_LNK = 10, // 符號連接 16 # define DT_LNK DT_LNK 17 DT_SOCK = 12, // 套接字 18 # define DT_SOCK DT_SOCK 19 DT_WHT = 14 20 # define DT_WHT DT_WHT 21 };
三、目錄文件的操做函數——opendir、readdir、closedir;this
opendir(打開目錄)spa
相關函數
|
open,readdir,closedir,rewinddir,seekdir,telldir,scandir |
表頭文件
|
#include<sys/types.h> #include<dirent.h> |
定義函數
|
DIR * opendir(const char * name); |
函數說明
|
opendir()用來打開參數name指定的目錄,並返回DIR*形態的目錄流,和open()相似,接下來對目錄的讀取和搜索都要使用此返回值。 |
返回值
|
成功則返回DIR* 型態的目錄流,打開失敗則返回NULL。 |
錯誤代碼
|
EACCESS 權限不足 EMFILE 已達到進程可同時打開的文件數上限。 ENFILE 已達到系統可同時打開的文件數上限。 ENOTDIR 參數name非真正的目錄 ENOENT 參數name 指定的目錄不存在,或是參數name 爲一空字符串。 ENOMEM 核心內存不足。 |
readdir(讀取目錄)code |
相關函數
|
open,opendir,closedir,rewinddir,seekdir,telldir,scandir |
表頭文件
|
#include<sys/types.h> #include<dirent.h> |
定義函數
|
struct dirent * readdir(DIR * dir); |
函數說明
|
readdir()返回參數dir目錄流的下個目錄進入點。 結構dirent定義以下 struct dirent { ino_t d_ino; ff_t d_off; signed short int d_reclen; unsigned char d_type; har d_name[256; }; d_ino 此目錄進入點的inode d_off 目錄文件開頭至此目錄進入點的位移 d_reclen _name的長度,不包含NULL字符 d_type d_name 所指的文件類型 d_name 文件名 |
返回值
|
成功則返回下個目錄進入點。有錯誤發生或讀取到目錄文件尾則返回NULL。 |
附加說明
|
EBADF參數dir爲無效的目錄流。 |
closedir(關閉目錄)blog
相關函數
|
opendir |
表頭文件
|
#include<sys/types.h> #include<dirent.h> |
定義函數
|
int closedir(DIR *dir); |
函數說明
|
closedir()關閉參數dir所指的目錄流。 |
返回值
|
關閉成功則返回0,失敗返回-1,錯誤緣由存於errno 中。 |
錯誤代碼
|
EBADF 參數dir爲無效的目錄流 |
範例
|
參考readir()。 |
四、代碼示例:遞歸
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <dirent.h> 4 #include <string.h> 5 #include <errno.h> 6 7 #if 0 8 struct dirent 9 { 10 long d_ino; /* inode number 索引節點號 */ 11 off_t d_off; /* offset to this dirent 在目錄文件中的偏移 */ 12 unsigned short d_reclen; /* length of this d_name 文件名長 */ 13 unsigned char d_type; /* the type of d_name 文件類型 */ 14 char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最長255字符 */ 15 } 16 17 // d_type表示檔案類型: 18 19 enum 20 { 21 DT_UNKNOWN = 0, //類型未知。少數文件系統會出現此函數不支持的文件類型,另外一些則老是返回這個值。譯者注:總之這個值是爲了應對不兼容的文件系統而設置的; 22 # define DT_UNKNOWN DT_UNKNOWN 23 DT_FIFO = 1, // 一個命名管道,或FIFO 24 # define DT_FIFO DT_FIFO 25 DT_CHR = 2, // 字符設備 26 # define DT_CHR DT_CHR 27 DT_DIR = 4, // 目錄 28 # define DT_DIR DT_DIR 29 DT_BLK = 6, // 塊設備 30 # define DT_BLK DT_BLK 31 DT_REG = 8, // 常規文件 32 # define DT_REG DT_REG 33 DT_LNK = 10, // 符號連接 34 # define DT_LNK DT_LNK 35 DT_SOCK = 12, // 套接字 36 # define DT_SOCK DT_SOCK 37 DT_WHT = 14 38 # define DT_WHT DT_WHT 39 }; 40 41 #endif 42 43 void listDir(char *dir) 44 { 45 DIR *dp; 46 struct dirent *dirp; 47 char childpath[512]; 48 49 memset(childpath,0,sizeof(childpath)); 50 if ((dp = opendir(dir)) == NULL) 51 { 52 printf("can't open the directory %s,Error = %s!\n",dir,strerror(errno)); 53 return; 54 } 55 56 while ((dirp = readdir(dp)) != NULL) 57 { 58 // printf("dir = %s,dir_type = %d,DT_DIR = %d\n",dirp->d_name,dirp->d_type,DT_DIR); 59 if (dirp->d_type == DT_DIR) 60 { 61 if (strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0) 62 continue; 63 sprintf(childpath,"%s/%s",dir,dirp->d_name); 64 printf("childpath = %s\n",childpath); 65 listDir(childpath); 66 } 67 else 68 { 69 printf("filename = %s\n",dirp->d_name); 70 } 71 } 72 closedir(dp); 73 } 74 75 int main(int argc,char *argv[]) 76 { 77 if (argc != 2) 78 { 79 printf("Usage: ls directory name!\n"); 80 return -1; 81 } 82 listDir(argv[1]); 83 return 0; 84 }