在Linux上递归搜索所有子目录中的文件

时间:2018-03-17 17:32:31

标签: c linux search directory

我正在尝试通过所有子目录搜索作为参数给出的文件。我的代码的问题是,当它到达一个不是目录的文件时,它会以perror("Error opening the directory\n");停止。

我无法找到克服这个问题的方法。我尝试了另一个if(S_ISREG...),但它没有用。

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

void check_file_existence(char *dirName,char *file){
    struct stat *metadata;
    char name[1000];
    struct dirent *dirEntry;
    struct stat bufstat;

    DIR *dir;

    dir = opendir(dirName);
    if (dir==NULL)
    {
        perror("Error opening the directory\n");
        exit(1);
    }

    while ((dirEntry = readdir(dir))!=NULL){
        lstat(dirEntry->d_name,&bufstat);

        if(S_ISDIR(bufstat.st_mode)){
            if (strcmp(dirEntry->d_name,".")==0 || strcmp(dirEntry->d_name,"..")==0){
                continue;
            }
            sprintf(name,"%s/%s",dirName,dirEntry->d_name);
            printf("%s\n",name);
            check_file_existence(name,file);
        }       
    }

    closedir(dir);
}

int main(int argc,char **argv){
    if (argc!=3){
        perror("Number of arguments is wrong.\n");
        exit(1);
    }

    check_file_existence(argv[1],argv[2]);  
}

1 个答案:

答案 0 :(得分:1)

这是您的代码,其中有一些简化的功能可以偶然地解决您的错误,还有两项改进。现在,它可以递归搜索目录树,以查找指定文件的首次出现。

我们使用dirEntry结构识别文件类型,并添加strcmp()来检查指定的文件。在dirEntry结构中使用d_type是确定文件类型的最简单方法,因此往往会降低错误率。

我们检查输入中是否有多余的斜杠。输入上的额外斜杠不会停止任何操作,但会使输出不太清晰。

为方便调试,我们大量使用了printf(),并添加了一个例程以字节转储dirEntry结构的内容,以帮助您更详细地了解正在发生的事情,因为它递归并循环遍历了目录和文件。

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

void debugbytes( char *s, unsigned short nlen, char dtype, char *nameptr ) {
  int n;
  printf( "\n%d %x ", nlen, dtype );
  switch( dtype )
    {
    case DT_BLK:
      printf( "BLK" );
      break;
    case DT_CHR:
      printf( "CHR" );
      break;
    case DT_DIR:
      printf( "DIR" );
      break;
    case DT_FIFO:
      printf( "FIFO" );
      break;
    case DT_LNK:
      printf( "LNK" );
      break;
    case DT_REG:
      printf( "REG" );
      break;
    case DT_SOCK:
      printf( "SOCK" );
      break;
    case DT_UNKNOWN:
      printf( "UNKOWN" );
      break;
    default:
      printf( "not recognized" );
    }
  printf( " %s :", nameptr );
  for (n = 0; n < nlen; n++ ) {
    printf( "%x", s[n] );
  }
  printf( "\n" );
}

void check_file_existence(char *dirName,char *file){

  DIR *dir;

  struct dirent *dirEntry;

  char name[1000];

  printf( "opening %s\n", dirName );

  dir = opendir(dirName);
  if (dir==NULL)
    {
      perror("Error opening the directory\n");
      exit(1);
    }

    while ((dirEntry = readdir(dir))!=NULL){

      debugbytes( (char *) dirEntry,  dirEntry->d_reclen, dirEntry->d_type, dirEntry->d_name );

      if ( dirEntry->d_type == DT_DIR ) {
        if (strcmp(dirEntry->d_name,".")==0 || strcmp(dirEntry->d_name,"..")==0){
        continue;
      }
      printf( "directory\n" );
      sprintf(name,"%s/%s",dirName,dirEntry->d_name);
      printf("\n%s\n",name);
      check_file_existence(name,file);
    }

    else if ( dirEntry->d_type == DT_REG ) {

      printf( "file %s/%s\n", dirName, (char *)dirEntry->d_name );

      if ( !strcmp( dirEntry->d_name, file ) ) {
        printf( "file found\n" );
        break;
      }
    }
  }

  closedir(dir);
}

int main(int argc,char **argv){
  char dirspec[256] = { 0 };
  int n;

    if (argc!=3){
        perror("Number of arguments is wrong.\n");
        exit(1);
    }

    n = strlen( argv[1] );
    while( (n > 1) && argv[1][n-1] == '/' ) n--; 

    strncpy(dirspec, argv[1], n );

    check_file_existence( dirspec, argv[2] );  
}

这是示例输出:

$ ./temp1 gEDA/ 1206P.fp
opening gEDA
.
.
.
32 4 DIR Footprints :3b04250000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f2004466f6f747072696e7473004
directory
.
.
.
32 8 REG 1206P.fp :ffffff8084250000ffffffd0ffffffff12ffffffeb7afffffff77052200831323036502e6670054ffffffa7ffffffce8
file gEDA/Footprints/1206P.fp
file found

$