基础练习1——ls的实现与递归
Posted ys6738-4271-3931
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基础练习1——ls的实现与递归相关的知识,希望对你有一定的参考价值。
学习贵在坚持,兜兜转转,发现还是从基础做起吧,打好基础,才会长期的坚持下去。。。
第一个练习:shell命令 “ls"的实现与递归
1、简介:ls 的作用是列举当前目录下所有的目录和文件。
2、用到的结构体——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 };
3、目录文件的操作函数——opendir、readdir、closedir;
opendir(打开目录)
相关函数
|
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(读取目录) |
相关函数
|
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(关闭目录)
相关函数
|
opendir |
表头文件
|
#include<sys/types.h> #include<dirent.h> |
定义函数
|
int closedir(DIR *dir); |
函数说明
|
closedir()关闭参数dir所指的目录流。 |
返回值
|
关闭成功则返回0,失败返回-1,错误原因存于errno 中。 |
错误代码
|
EBADF 参数dir为无效的目录流 |
范例
|
参考readir()。 |
4、代码示例:
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! ",dir,strerror(errno)); 53 return; 54 } 55 56 while ((dirp = readdir(dp)) != NULL) 57 { 58 // printf("dir = %s,dir_type = %d,DT_DIR = %d ",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 ",childpath); 65 listDir(childpath); 66 } 67 else 68 { 69 printf("filename = %s ",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! "); 80 return -1; 81 } 82 listDir(argv[1]); 83 return 0; 84 }
以上是关于基础练习1——ls的实现与递归的主要内容,如果未能解决你的问题,请参考以下文章