目录检索

1.概念引入

目录IO的作用(开发的应用场景):实现目录检索find,显示目录中的目录项显示ls

目录IO基本的函数:
        opendir:打开一个目录
        closedir:关闭一个目录
        readdir:读取一个目录里面的一个目录项(获取目录中的目录项信息--就是说这个文件夹里面有什么东西)
        
        
        目录:文件 目录            目录项
        钱包:钱  银行卡 身份证... 钱包项

2.opendir:打开一个目录

    #include <dirent.h>

       DIR *opendir(const char *name); FILE * 类似,都是指向结构体的指针,结构体多是存放对应对象的元信息
       
       返回值:RETURN VALUE
       The opendir() functions return a pointer to the directory stream(数据流:字节流).  (打开的目录里面的)目录信息当成数据字节流来传输
       On error, NULL is returned, and errno is set appropriately.
       成功:返回一个目录流指针,这个流指针同理也会指向一个结构体,该结构体存放的信息用于对应该目录项的操作(读取 关闭)。
       失败:NULL
       形参1:
           设置你要打开的目录的路径
           
        目录项 = 文件 + 文件夹

3.closedir:关闭一个目录

 #include <sys/types.h>
   #include <dirent.h>
   int closedir(DIR *dirp);
   
   形参1:opendir打开目录成功的返回值(目录流指针)
   返回值: The closedir() function returns 0 on success.  On error, -1 is returned, 
       关闭成功:
               0
        关闭失败:
              -1

4.readdir:读取一个目录

      #include <dirent.h>

       struct dirent * readdir(DIR *dirp);
                                                               
       返回值: On success, readdir() returns a pointer to a dirent structure.(指向目录项的结构体。该结构体里面存放的就是我们需要获取的信息) 
       返回下一个目录项的结构体的首地址,这个结构体就存放了对应的目录项的信息(目录项的名字和大小等信息).

       If the end of the directory stream is reached, NULL is returned and errno is not changed.  If an error occurs, NULL is returned
       读取成功:返回下一个目录项的结构体指针,这个结构体指针就是存放下一个目录项的信息。
       读取失败:NULL
       读到目录流末尾:NULL
       形参1:opendir打开目录成功的返回值(目录流指针)
       
   struct dirent {
               ino_t          d_ino;       /* Inode number  --- 目录项的索引号*/
               off_t          d_off;       /* Not an offset; see below */ 目录项在该目录里面的偏移量
               unsigned short d_reclen;    /* Length of this record */ 目录项的实际大小 -- 受名字的长度影响
               unsigned char  d_type;      /* Type of file; not supported 目录项的类型(主要的信息)
                                              by all filesystem types */
               char           d_name[256]; /* Null-terminated filename */ 目录项的名字(主要的信息)
           };                                          

1).关于readdir:

image


2).目录项类型分类:

image


5.目录检索的实现

image

/******************************************************************************************************
 * @file name:		  : 目录检索.c
 * @brief  		      :检索所提供的文件名是否存在
 * @author 		      :wvjnuhhail@126.com
 * @date 			      :2024/07/11
 * @version 1.0 	  :V1.0
 * @property 		    :暂无
 * @note   		      :None
 * CopyRight (c)  2023-2024   wvjnuhhail@126.com   All Right Reseverd
 *******************************************************************************************************/
/*
  实现思路:
    了解读取目录项的顺序

    读取目录的特点:不管什么时候,遇到目录就需要立刻打开这个目录进去读取里面的目录项

    int Fun(目录的路径)
    {
        opendir()

        while(1)
        {
            readdir();

            如果是读到文件夹
            Fun(新的文件夹的路径)

            如果是文件呢?
            strcmp

        }
    }
 */
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>

#define PATH_MAN_LEN 256 * 50

/*******************************************************************************************************
 * @funname         :	SearchFile
 * @brief           : 拷贝文件
 * @param           :
 *                  @a:obj_dir
 *                  @b:obj_file
 * @retval          : int
 * @date 			      :2024/07/11
 * @version         :V1.0
 * @note   		      :None
 *******************************************************************************************************/
// 传入检索的目录,需要检索的文件
int SearchFile(const char *obj_dir, const char *obj_file)
{
  // 打开目录
  DIR *dp = opendir(obj_dir);
  if (NULL == dp)
  {
    perror("opendir...");
    exit(1);
  }
  // 定义一个结构体指针
  struct dirent *eq;

  char complete_path[PATH_MAN_LEN];

  while (1)
  {
    memset(complete_path, 0, PATH_MAN_LEN);
    eq = readdir(dp);
    if (eq == NULL)
    {
      break;
    }
    // 检索第一个元素下标是0,成员是  "."
    if (eq->d_name[0] == '.')
    {
      continue;
    }
    if (obj_dir[strlen(obj_dir) - 1] == '/')
    {
      // 有输入'/',不需要补全
      sprintf(complete_path, "%s%s", obj_dir, eq->d_name);
    }
    else
    {
      // 终端没有输入'/',补全
      sprintf(complete_path, "%s/%s", obj_dir, eq->d_name);
    }
    // 判断如果是目录,递归检索
    if (eq->d_type == DT_DIR)
    {
      // 拼接后的路径保存在数组complete_path中
      SearchFile(complete_path, obj_file);
    }

    // 如果是文件
    if (eq->d_type == DT_REG)
    {
      // 与所给的名字进行匹配
      if (strcmp(eq->d_name, obj_file) == 0)
      {
        printf("Hit Obj ----%s\n", complete_path);
      }
    }
    else
    {
      // 假如查找的文件不存在,提示未找到
      printf("Not Find\n");
      break;
    }
  }

  closedir(dp);

  return 0;
}

int main(int argc, char *argv[])
{

  if (argc != 3)
  {
    printf("参数有误,需要3个参数!\n");
    return -1;
  }

  if (SearchFile(argv[1], argv[2]) == -1)
  {
    printf("目录检索失败!\n");
    return -1;
  }

  return 0;
}
posted @ 2024-07-11 19:17  WJnuHhail  阅读(1)  评论(0编辑  收藏  举报