• MIB 6.1810实验Xv6 and Unix utilities(5)find


    难度:moderate

    Write a simple version of the UNIX find program for xv6: find all the files in a directory tree with a specific name. Your solution should be in the file user/find.c.

    题目要求:实现find ,即在某个路径中,找出某个文件

    1. #include "kernel/types.h"
    2. #include "kernel/stat.h"
    3. #include "user/user.h"
    4. #include "kernel/fs.h"
    5. #include "kernel/fcntl.h"
    6. char* fmt_name(char *path){
    7. static char buf[DIRSIZ+1];
    8. char *p;
    9. //find first character after last slash
    10. for(p=path+strlen(path);p>=path&&*p!='/';p--);
    11. p++;
    12. memmove(buf,p,strlen(p)+1);
    13. return buf;
    14. }
    15. void eq_print(char *fileName,char *findName){
    16. if(strcmp(fmt_name(fileName),findName)==0){
    17. printf("%s\n",fileName);
    18. }
    19. }
    20. void find(char *path,char *findName){
    21. char buf[512], *p;
    22. int fd;
    23. struct dirent de;
    24. struct stat st;
    25. if((fd = open(path, O_RDONLY)) < 0){
    26. fprintf(2, "ls: cannot open %s\n", path);
    27. return;
    28. }
    29. if(fstat(fd, &st) < 0){
    30. fprintf(2, "ls: cannot stat %s\n", path);
    31. close(fd);
    32. return;
    33. }
    34. /*
    35. int fd;声明一个文件描述符变量 fd,用于在程序中表示打开的文件或目录。
    36. struct dirent de;定义了一个结构体 dirent 变量 de,通常用于存储读取目录时的目录项信息。
    37. struct stat st;:定义了一个结构体 stat 变量 st,用于存储文件或目录的状态信息。
    38. if((fd = open(path, O_RDONLY)) < 0){ ... }:尝试以只读模式打开指定路径的文件或目录。如果 open() 函数返回的文件描述符小于 0(表示打开失败),则输出错误信息,并返回。
    39. if(fstat(fd, &st) < 0){ ... }:如果文件或目录成功打开,则使用 fstat() 函数获取文件描述符 fd 对应文件或目录的状态信息,并将结果存储在 st 结构体中。如果获取状态信息失败(fstat() 返回值小于 0),则输出错误信息,并关闭文件描述符后返回。
    40. */
    41. switch(st.type){
    42. case T_DEVICE:
    43. case T_FILE:
    44. eq_print(path,findName);
    45. break;
    46. case T_DIR:
    47. if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
    48. printf("find: path too long\n");
    49. break;
    50. }
    51. strcpy(buf, path);
    52. p = buf+strlen(buf);
    53. *p++ = '/';
    54. while(read(fd, &de, sizeof(de)) == sizeof(de)){
    55. if(de.inum ==0||de.inum==1||strcmp(de.name,".")==0 || strcmp(de.name,"..")==0)
    56. continue;
    57. memmove(p, de.name, strlen(de.name));
    58. p[strlen(de.name)] = 0;
    59. find(buf,findName);
    60. }
    61. break;
    62. /*
    63. 循环:遍历目录项
    64. read(fd, &de, sizeof(de)):使用read函数从文件描述符 fd中读取一个目录项的内容,并将读取的内容存储在 de 变量中。
    65. 只要 read 函数成功读取一个目录项的大小(sizeof(de)),就会继续执行循环。
    66. 循环内部:
    67. 首先,通过检查 de.inum(目录项的inode号码)是否等于0或1,以及检查目录项的名称是否是.或..,来过滤掉特殊的目录项。
    68. .(点)表示当前目录,..(点点)表示父目录,它们在此处被跳过,不做进一步处理。
    69. 如果目录项既不是特殊目录项.(点)或 ..(点点),也不是 inode 号码为 0 或 1,则会执行以下操作:
    70. memmove(p, de.name, strlen(de.name));:将目录项的文件名 de.name 复制到一个指定的缓冲区 buf 中,从指针 p 指向的位置开始存储。
    71. 这里使用 memmove 函数是为了确保将文件名正确复制到指定的位置。
    72. p[strlen(de.name)] = 0;:在复制文件名后,将字符串末尾添加一个空字符 \0,以确保字符串以空字符结尾,形成一个 C 风格的字符串。
    73. 最后,调用 find(buf, findName);,以递归方式在当前路径下的子目录中继续查找名为 findName 的文件或目录。
    74. 在当前目录下的每个子目录中进行深度优先的查找操作。
    75. */
    76. }
    77. close(fd);
    78. }
    79. /*
    80. void find(char *path, char *findName):
    81. 递归函数,接收两个参数,path 表示要搜索的路径,findName 表示要查找的文件或目录名。
    82. 代码开始通过 open() 函数尝试打开指定的路径,如果失败则会输出错误信息并返回。
    83. 使用 fstat() 函数获取文件的状态信息,如果失败也会输出相应的错误信息并关闭文件描述符后返回。
    84. 接下来 定义了一个缓冲区buf和指针p,用于构建要查找的文件或目录的完整路径。
    85. 使用 switch 语句检查文件类型:
    86. T_FILE:表示当前路径是一个文件,则调用 eq_print() 函数
    87. T_DIR:表示当前路径是一个目录,则进行目录的遍历和递归查找。
    88. 首先检查路径长度是否过长,如果是,则输出相应错误信息。然后将当前路径复制到 buf 中,并在其末尾添加 /。
    89. 接着使用 read() 函数读取目录项,并在循环中遍历目录下的所有文件和子目录。
    90. 在目录遍历的循环中,会检查每个目录项的 inum 值是否为0或1(通常表示未使用的或损坏的inode),以及是否是.或..目录(表示当前目录和父目录).
    91. 如果是则跳过不处理。
    92. 将当前目录项的名字添加到 buf 中,并递归调用 find() 函数,以此在当前目录中查找与 findName 匹配的文件或目录。
    93. 最后关闭打开的文件描述符 fd。
    94. */
    95. int main(int argc, char *argv[])
    96. {
    97. if(argc>3){
    98. printf("find: find \n");
    99. exit(0);
    100. }
    101. find(argv[1],argv[2]);
    102. exit(0);
    103. }

    fmtname函数示意图 

    find函数示意图:

     

    实验结果:

  • 相关阅读:
    机器学习:VC维的概念和用途
    抖音小店无货源,怎么能找到靠谱的货源?怎么和厂家进行沟通?
    【AI理论学习】对Transformer中Positional Encoding的理解
    八.Redis 主从复制
    炫我科技成功为乐歌提供渲染私有云系统解决方案
    【算法】剑指offer-栈的压入,弹出序列&&从上到下打印二叉树
    【语义分割】2017-PSPNet CVPR
    单个脚本打包成jar可以直接运行
    基于Spring Boot+Vue的健身房管理系统(协同过滤算法、功能非常多)
    Git基本常用命令
  • 原文地址:https://blog.csdn.net/m0_52043808/article/details/134466762