基礎練習1——ls的實現與遞歸

  學習貴在堅持,兜兜轉轉,發現仍是從基礎作起吧,打好基礎,纔會長期的堅持下去。。。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 }
View Code

  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 }; 
View Code

  三、目錄文件的操做函數——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 }
View Code
相關文章
相關標籤/搜索