C 查找包含搜索项(子元素除外)的所有文件

C 查找包含搜索项(子元素除外)的所有文件,c,string,dirent.h,C,String,Dirent.h,我正在尝试制作一个C程序,它将显示包含给定搜索词的所有文件和文件夹。执行程序时,搜索项作为参数给出。如果文件夹/文件的名称包含搜索词(不区分大小写),则该文件夹/文件将显示为标准输出。 但困难在于我不想输出包含搜索词的文件夹中包含的文件和子文件夹。下面是一个例子: 假设我的搜索词是docker,这是当前输出: "/Users/me/.docker" "/Users/me/.docker/contexts" "/Users/me/.docker/c

我正在尝试制作一个C程序,它将显示包含给定搜索词的所有文件和文件夹。执行程序时,搜索项作为参数给出。如果文件夹/文件的名称包含搜索词(不区分大小写),则该文件夹/文件将显示为标准输出。 但困难在于我不想输出包含搜索词的文件夹中包含的文件和子文件夹。下面是一个例子:

假设我的搜索词是docker,这是当前输出:

"/Users/me/.docker"
"/Users/me/.docker/contexts"
"/Users/me/.docker/contexts/meta"
"/Users/me/.docker/config.json"
"/Users/me/.docker/scan"
"/Users/me/.docker/scan/config.json"
"/Users/me/.docker/application-template"
"/Users/me/.docker/application-template/logs"
"/Users/me/.docker/application-template/logs/com.docker.log"
"/Users/me/.docker/daemon.json"
"/Users/me/.docker/run"
"/Users/me/Library/Application Support/Docker Desktop"
"/Users/me/Library/Application Support/Docker Desktop/blob_storage"
"/Users/me/Library/Application Support/Docker Desktop/blob_storage/6965e70b-e33a-4415-b9a8-e19996fe221d"
但这是我试图实现的输出:

"/Users/me/.docker"
"/Users/me/Library/Application Support/Docker Desktop"
以下是我目前的代码:

#包括
#包括
#包括
#包括
静态整型显示信息(常量字符*fpath,常量字符*fname,常量字符*term){
int what_len=strlen(术语);
整数计数=0;
char*where=fpath;
如果(什么){
while((其中=strcasestr(其中,术语))){
其中+=什么内容;
计数++;
}
如果(计数=1){
printf(“\%s/%s\”\n”,fpath,fname);
}
}
返回0;
}
静态void列表文件递归(char*basePath,const char*searchTerm){
字符路径[1000];
结构方向*dp;
DIR*DIR=opendir(基本路径);
//无法打开目录流
如果(!dir)
返回;
而((dp=readdir(dir))!=NULL){
如果(strcmp(dp->d_name,“.”)=0和&strcmp(dp->d_name,“…”)!=0){
//printf(“%s%hhu%s\n”,基本路径,dp->d_类型,dp->d_名称);
显示_信息(基本路径、dp->d_名称、搜索术语);
//从基本路径构造新路径
strcpy(路径、基本路径);
strcat(路径“/”;
strcat(路径,dp->d_名称);
递归地列出文件(路径、搜索项);
}
}
closedir(dir);
}
int main(int argc,const char*argv[]{
char*home=getenv(“home”);
如果(argc==2){
递归地列出文件(home,argv[1]);
}否则{
printf(“请提供一个参数”);
}
返回0;
}

非常感谢您的反馈,谢谢

多亏了@KamilCuk,我才得以解决我的问题。下面是我的最后一个递归
列表文件
函数:

静态void列表文件递归(char*basePath,const char*searchTerm){
字符路径[1000];
结构方向*dp;
DIR*DIR=opendir(基本路径);
//无法打开目录流
如果(!dir)
返回;
而((dp=readdir(dir))!=NULL){
如果(strcmp(dp->d_name,“.”)=0和&strcmp(dp->d_name,“…”)!=0){
if(strcasestr(dp->d_名称,searchTerm)){
printf(“%s/%s\n”,基本路径,dp->d_名称);
递归地列出文件(路径、搜索项);
}否则{
//从基本路径构造新路径
strcpy(路径、基本路径);
strcat(路径“/”;
strcat(路径,dp->d_名称);
递归地列出文件(路径、搜索项);
}
}
}
closedir(dir);
}
  • 我不确定我是否理解
    display\u info()的逻辑
  • listFilesRecursively()
    上,不能在调用之间重复使用
    path
  • main()
    应该是代码中的第一个函数,可能在单独的文件中
替代方案 我将添加一个C示例,以递归方式更改您的
列表文件()

  • 不使用void(),因此可以返回-1表示错误
  • 测试
    在循环开始时,仅使用
    continue
    可能会使代码更易于阅读
  • path
    在本地分配,返回时
    free()
  • strstr\u ign()
    是一个不区分大小写的版本,用于模式搜索
更改后的
列表文件()的代码
strstr\u ign()的代码
我讨厌
strstr()
的参数顺序,但把它保留在这里只是为了让事情变得平等。这样就可以使用
strstr\u ign()
替换
strstr()
,而无需更改参数的顺序。我认为
pinder
应该放在第一位:)一种语言:大海捞针比大海捞针要普遍得多,但是肯和丹尼斯有他们的理由写
strstr()

//
// strstr() ignoring case
//
char*       strstr_ign(const char* haystack, const char* needle)
{
    if (needle == NULL) return NULL;
    if (haystack == NULL) return NULL;
    if (*needle == 0)
    {
        if (*haystack == 0)
            return (char*) haystack;
        else
            return NULL;
    }
    int limit = strlen(haystack) - strlen(needle);
    for (int x = 0; x <= limit; x += 1)
    {   // search for needle at position 'x' of 'haystack'
        int here = 1;
        for (unsigned y = 0; y < strlen(needle); y += 1)
        {
            if ( tolower(haystack[x + y]) != tolower(needle[y]) )
            {
                here = 0; break;
            };
        };
        if ( here == 1) return (char*)(haystack + x);
    }
    return NULL;
};
此测试的C代码 模拟测试:)

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int显示信息(常量字符*,常量字符*);
int list_文件(char*,char*);
字符*字符串符号(常量字符*,常量字符*);
int main(int argc,const char*argv[]
{
字符搜索项[80];
如果(argc>=2)
{
if(strlen(argv[1])>(sizeof(搜索词)-1))
{
printf(“子字符串(%zd)的大小不能大于%zd\n”,
strlen(argv[1]),sizeof(搜索词)-1;
返回-1;
}
对于(int i=0;id_name,“.”==0)继续;
如果(strcmp(dp->d_name,“..”)==0)继续;
if(strstr_ign((const char*)dp->d_name,pattern)!=NULL)
{
显示信息(基本路径,dp->d\U名称);
}
其他的
{
char*path=(char*)malloc(1+strlen(dp->d_name)+strlen(base_path)+1);
sprintf(路径,“%s/%s”,基本路径,dp->d\U名称);
列出_文件(模式、路径);
自由(路径);//使用路径确定
}
};//while()
closedir(dir);
返回0;
};  // 列表_文件()
//
//strstr()忽略大小写
//
字符*字符串符号(常量字符*干草堆,常量字符*针)
{
如果(指针==NULL)返回NULL;
if(haystack==NULL)返回NULL;
如果(*指针==0)
{
如果(*干草堆==0)
返回(char*)干草堆;
//
// strstr() ignoring case
//
char*       strstr_ign(const char* haystack, const char* needle)
{
    if (needle == NULL) return NULL;
    if (haystack == NULL) return NULL;
    if (*needle == 0)
    {
        if (*haystack == 0)
            return (char*) haystack;
        else
            return NULL;
    }
    int limit = strlen(haystack) - strlen(needle);
    for (int x = 0; x <= limit; x += 1)
    {   // search for needle at position 'x' of 'haystack'
        int here = 1;
        for (unsigned y = 0; y < strlen(needle); y += 1)
        {
            if ( tolower(haystack[x + y]) != tolower(needle[y]) )
            {
                here = 0; break;
            };
        };
        if ( here == 1) return (char*)(haystack + x);
    }
    return NULL;
};
    - "./hms.c" [size: 1546]
    d "./sub/1/xyzHMSxyz"   [last access: Sat Apr 24 12:38:04 2021]
int display_info(const char* base, const char* file)
{
    struct  stat Stats;
    char*   path = (char*)malloc(1 + strlen(base) + strlen(file) + 1);
    char    atime[40];
    sprintf(path, "%s/%s", base, file);
    if ( stat(path, &Stats) < 0)
    {
        perror("Inside display_info()");
        free(path);
        return -1;
    }
    if ( S_ISDIR(Stats.st_mode) )
    {
        strftime( atime, sizeof(atime), "%a %b %d %H:%M:%S %Y", localtime(&Stats.st_atime) );
        printf("\td \"%s/%s\"\t[last access: %s]\n", base, file, atime );
    }
    else
    {
        if ( S_ISREG(Stats.st_mode) )
            printf("\t- \"%s/%s\"\t[size: %ld]\n", base, file, Stats.st_size );
        else
            printf("is somthing else\n");
    }
    free(path);
    return 0;
}
Search pattern is "hms" (case is ignored) 
    - "./hms"   [size: 16848]
    - "./hms-soma.c"    [size: 1379]
    - "./hms.c" [size: 1546]
    d "./sub/1/xyzHMSxyz"   [last access: Sat Apr 24 12:38:04 2021]
    d "./sub/2/xyzHMS"  [last access: Sat Apr 24 12:21:11 2021]
    d "./sub/hMs"   [last access: Sat Apr 24 12:21:11 2021]
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>


int         display_info(const char*, const char*);
int         list_files(char*, char*);
char*       strstr_ign(const char*, const char*);

 int main(int argc, const char * argv[])
 {
     char    search_term[80];
     if (argc >= 2)
     {
         if ( strlen(argv[1]) > (sizeof(search_term)-1) )
         {
             printf("Size of substring (%zd) must not be greater than %zd\n",
             strlen(argv[1]), sizeof(search_term)-1 );
             return -1;  
         }
         for ( int i = 0; i<= strlen(argv[1]); search_term[i] = (char)(tolower(argv[1][i])), i+=1 ); 
         printf("Search pattern is \"%s\" (case is ignored) \n", search_term );
         list_files(search_term,".");
     } else {
         printf("Please provide pattern to search for.\n");
     }
     return 0;
 };  // main()


int display_info(const char* base, const char* file)
{
    struct  stat Stats;
    char*   path = (char*)malloc(1 + strlen(base) + strlen(file) + 1);
    char    atime[40];
    sprintf(path, "%s/%s", base, file);
    if ( stat(path, &Stats) < 0)
    {
        perror("Inside display_info()");
        free(path);
        return -1;
    }
    if ( S_ISDIR(Stats.st_mode) )
    {
        strftime( atime, sizeof(atime), "%a %b %d %H:%M:%S %Y", localtime(&Stats.st_atime) );
        printf("\td \"%s/%s\"\t[last access: %s]\n", base, file, atime );
    }
    else
    {
        if ( S_ISREG(Stats.st_mode) )
            printf("\t- \"%s/%s\"\t[size: %ld]\n", base, file, Stats.st_size );
        else
            printf("is somthing else\n");
    }
    free(path);
    return 0;
}


int list_files(char* pattern, char* base_path)
{
    struct dirent* dp;
    DIR* dir = opendir(base_path);
    if (!dir) return -1; // Unable to open directory stream
    while ((dp = readdir(dir)) != NULL)
    {
        if (strcmp(dp->d_name, ".") == 0) continue;
        if (strcmp(dp->d_name, "..") == 0) continue;
        if ( strstr_ign((const char*)dp->d_name, pattern) != NULL )
        {
            display_info(base_path, dp->d_name);
        }
        else
        {
            char* path = (char*)malloc(1 + strlen(dp->d_name) + strlen(base_path) + 1);
            sprintf(path, "%s/%s", base_path, dp->d_name);
            list_files(pattern, path);
            free(path); // ok with path
        }
    };  // while()
    closedir(dir);
    return 0;
};  // list_files()

//
// strstr() ignoring case
//
char*       strstr_ign(const char* haystack, const char* needle)
{
    if (needle == NULL) return NULL;
    if (haystack == NULL) return NULL;
    if (*needle == 0)
    {
        if (*haystack == 0)
            return (char*) haystack;
        else
            return NULL;
    }
    int limit = strlen(haystack) - strlen(needle);
    for (int x = 0; x <= limit; x += 1)
    {   // search for needle at position 'x' of 'haystack'
        int here = 1;
        for (unsigned y = 0; y < strlen(needle); y += 1)
        {
            if ( tolower(haystack[x + y]) != tolower(needle[y]) )
            {
                here = 0; break;
            };
        };
        if ( here == 1) return (char*)(haystack + x);
    }
    return NULL;
};