C语言中关于对目录的操作

原文地址:C语言中关于对目录的操作

   

 目录的操作不论是在嵌入式产品还是应用软件编程都是必不可少的,不同的开发语言可能略有不同,笔者主要是讨论在Linux平台下对目录的一系列操作:

 

  1、获取当前目录操作:

     在系统命令行下我们可以直接输入命令:pwd 来获取当前的工作目录,但是你知道这个命令是怎么执行的吗?它是由系统通过 Shell 程序来解释执行的,在我们自己编写程序的时候怎么能获取当前的工作目录呢?在标准C库中提供了一系列关于目录操作的接口函数:

 

          char * getcwd(char * buf,size_t size);

 

       getcwd函数把当前目录的名字写到给定的缓冲区buf里。如果目录的名字超出了参数size给出的缓冲区长度(一个ERANGE错误),它就返回NULL。如果成功,它返回指针buf,我们可以访问buf来获取当前的目录。可能当你获取目录后可能需要进入这个目录或者跳到该目录的父目录,我们怎么操作呢?

 

  2、  切换目录:

 

           int chdir(const char *path);

       就像我们在shell里使用cd命令来切换目录一样,在程序里则可以使用chdir系统调用来实现目录的变更,一般情况下是配合 Getcwd 函数一起使用来实现目录定位操作。 

 

 3、 目录的创建和删除:

 

       在系统命令行下我们可以通过 “ mkdir” , “ rmdir” 命令通过Shell来实现帮我们创建一个目录和删除一个目录,如果在实际的产品开发中呢,总不可能我们自己去手动创建吧,很多情况下都是通过程序自动帮我们创建一个目录来存放相应的文件。系统I/O库中提供了下面相应的操作接口:

 

        int mkdir(const char * path,mode_t mode);

 

   mode的含义将按open系统调用的O_CREAT选项中的有关定义设置,当然,它还要服从umask的设置况。     

 

          int rmdir(const char *path);

 

  4、 目录扫描:

 

         对目录的扫描操作和文件的操作有点类似,都是通过对目录结构体的操作,这个结构是系统维护的,一般情况下用户不要去更改这个目录结构体中的相应字段:

 

   struct dirent {
                   ino_t          d_ino;      
                   off_t          d_off;      
                   unsigned short d_reclen;   
                   unsigned char  d_type;     
                   char           d_name[256];
               };

通过这个结构我们可以方便的实现文件的过滤,通过访问结构体中的 “d_type” 和 “d_name” 变量可以非常方便的实现文件的查找,文件的访问,文件的过滤。要实现一系列的目录操作你总的先把这个目录打开吧:

 

   打开目录:

                  DIR * opendir(const char *name)

         

                  函数返回一个目录结构指针,所以在使用该函数时,我们需要显示的定义相应的指针变量:

         

                eg :   DIR *dpt;

  读目录操作:

                

             struct dirent *readdir(DIR *dir);

     

       函数实现目录读操作,将目录流指针所指的目录读到相应的目录结构中,函数返回该结构的指针,所以我们在使用该接口之前我们需要显示的定于一个结构变量来接受函数的返回。

 

      如:           struct dirent *dir;

                     dir = readdir(DIR *dpt);

 

    在我们对目录的操作过程中你可能需要目录指针卷绕操作,在C标准库中也提供了相应的操作,和文件很相似吧 ,下面我们来看看:

 

                      void rewinddir(DIR *dir);

 

 目录扫描:

              int scandir(const char *dir,     struct dirent ***namelist,
                           int(*filter)(const struct dirent *),
              int(*compar)(const struct dirent **, const struct dirent **));

 

 

             int alphasort(const void *a, const void *b);
             int versionsort(const void *a, const void *b);

              

   咋一眼看到这个函数,复杂吧? 可能你在想我自己写个目录扫描小程序还简单呢?后面我们将提供一个这样小程序代码,我们先看这个函数的使用吧:

 

      参数: const char *dir   ----------------------------------> 要扫描的目录指针

          struct dirent ***namelist ------------------------->要扫描的目录结构

          int(*filter)(const struct dirent *) -------------->要过滤的条件

          int(*compar)(const struct dirent **, const struct dirent **));

                                  ---------------------------------->  扫描过程中要到的排序算法

 

  下面是Linux系统自带的一个使用例子可以帮我理解该函数的使用:

 


#include <dirent.h>
int main(void)

{
   struct dirent **namelist;
   int n;

   n = scandir(".", &namelist, 0, alphasort);
   if (n < 0)
      perror("scandir");
   else {
      while(n--)

      {
         printf("%sn", namelist[n]->d_name);
         free(namelist[n]);
      }
         free(namelist);
   }

          return 0;
}

 例2:  自己实现一个目录扫描操作:

#include <sys/types.h>
#include <dirent.h>

#include <sys/stat.h>
#include <unistd.h>


#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#define MAX_DIR_ENT 1024

typedef  int(*qsort_compar)(const void *, const void *);

int hxy_scandir(const char *dir, struct dirent ***namelist,
              int(*filter)(const struct dirent *),
              int(*compar)(const struct dirent **, const struct dirent **))
{
  DIR * od;
  int n = 0;
  struct dirent ** list = NULL;
  struct dirent * ent ,* p;
 
  if((dir == NULL) || (namelist == NULL))
    return -1;
   
  od = opendir(dir);
  if(od == NULL)
    return -1;
   
  
  list = (struct dirent **)malloc(MAX_DIR_ENT*sizeof(struct dirent *));
 
 
   while(( ent = readdir(od)) != NULL)
    {
       if(filter!=NULL && !filter(ent))
         continue;
       
          p =  (struct dirent *)malloc(sizeof(struct dirent));
         
          memcpy((void *)p,(void *)ent,sizeof(struct dirent));
          list[n] = p;
         
          n++;
          if(n >= MAX_DIR_ENT)
            break;
       
    }
      
    closedir(od);
  
   
    *namelist  = realloc((void *)list,n*sizeof(struct dirent *));
     if(*namelist == NULL)
        *namelist = list;
 

     
    if(compar)
       qsort((void *)*namelist,n,sizeof(struct dirent *),(qsort_compar)compar); 
    
    return n; 
  
}

 

int filter_fn(const struct dirent * ent)
 {
   if(ent->d_type != DT_REG)
     return 0;
    
   return (strncmp(ent->d_name,"lib",3) == 0);
 }

typedef int(*scandir_compar)(const struct dirent **, const struct dirent **);

//第二个版本的扫描目录程序,
void scan_lib(const char * dir_name)
{
  int n;
   struct dirent **namelist;
 
 
  n = hxy_scandir(dir_name, &namelist, filter_fn, (scandir_compar)alphasort);
   if (n < 0)
        perror("scandir");
   else {
               while(n--)

               {
                   printf("%sn", namelist[n]->d_name);
                   free(namelist[n]);
               }
                 free(namelist);
           }

  
}

int main(void)
{
  scan_lib("/usr/lib");
  return 0;

}

 

例3:

 

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

int scan_file(char *dir_name)
{
  DIR *dir;
  struct dirent *ent;
  char *ptr;
 
  dir = opendir(dir_name);
 
  
  if(dir == NULL)
  {
    fprintf(stderr,"open directory %s n",dir_name);
    return -1;
  }
 while( (ent = readdir(dir)) != NULL)
  {

  
     ptr = strrchr(ent->d_name,'.');
     if(ptr && (strcasecmp(ent->d_name, ".txt") == 0))

     printf("%sn", ent->d_name);
  }
    closedir(dir);
}

int main(void)
{
  scan_file("/root/Desktop/C/src");
}            

 

    5、目录关闭:

            int closedir(DIR *dpt);

 

一些文件操作函数:http://blog.csdn.net/wh_19910525/article/details/13503221

         http://blog.csdn.net/simmerlee/article/details/8281399

 

posted @ 2016-09-03 23:11  Grace、  阅读(4060)  评论(0编辑  收藏  举报