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

标签 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]);  
}

最佳答案

这是您的代码,其中进行了一些简化,顺便解决了您的错误,并进行了两项改进。它现在可以通过目录树递归搜索以找到指定文件的第一次出现。

我们使用 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

$

关于c - 在 Linux 上递归搜索所有子目录中的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49339844/

相关文章:

java - "Simulating"一个 64 位整数和两个 32 位整数

linux - NASM Linux 中的 strlen

带有包含的 WPF 组合框文本搜索

c - 编写一个简单程序的菜单阶段

c++ - 将指向数组的指针传递给 C 和 C++ 中的函数的两个不同结果?

c++ - 网络应用程序有多少传入缓冲区?

python - 如果列表包含字符串,则打印列表中包含它的所有索引/元素

javascript - 在Javascript中获取多维数组中元素的坐标

python - 在常见的实现中,realloc 实际上会缩小缓冲区吗?

linux - 64 位 Linux 机器上的 32 位 Weblogic 服务器