linux c 文件内容搜索小工具

时间:2022-02-25 05:35:36

经常需要在项目中搜索指定字符串,又不想打开ide,于是自己谢了个简单的搜索工具:搜索指定目录下所有包含指定字符串的文件。

很简单:扫描指定目录下的所有文件,依次以文本方式打开所有文件,逐行读取内容进行搜索;如果包含要搜索的字符串,就输出。

在输出的时候,使用ascii码对匹配的搜索串做了高亮显示。


代码如下:

linux c 文件内容搜索小工具linux c 文件内容搜索小工具View Code
  1  #include  < stdio.h >
  2  #include  < dirent.h >
  3  #include  < string .h >
  4  #include  < errno.h >
  5 
  6  #define  _DEBUG
  7 
  8  #define  USAGE printf("usage:\e[1mxsearch\e[0m \e[4mDIRECTORY\e[0m \e[4mKEYWORDS\e[0m\n"); return -1;
  9 
 10  static   char  szBase[ 512 =  { 0 };
 11  static   char  szKey[ 512 =  { 0 };
 12 
 13  int  search_inline( char *  file,  char *  line,  int  nline)
 14  {
 15       int  ret  =   - 1 ;
 16      
 17       char *  p  =  strstr(line, szKey);
 18       if (p  ==  NULL)
 19      {
 20           return  ret;
 21      }
 22       // printf("\e[34m[%s-%d]\e[0m%s", file, nline+1, line);
 23      printf( " \e[34m\e[1m[%s-%d]\e[0m " , file, nline + 1 );
 24      
 25       char *  pTemp  =  line;
 26       char *  pTail  =  (p  +  strlen(szKey));
 27       while (p)
 28      {
 29           while (pTemp  !=  p)
 30          {
 31              printf( " %c " * pTemp);
 32              pTemp  ++ ;
 33          }
 34          printf( " \e[31m\e[1m%s\e[0m " , szKey);
 35          
 36          p  +=  strlen(szKey);
 37          pTail  =  pTemp  =  p;
 38 
 39          p  =  strstr(p, szKey);
 40      }
 41      printf(pTail);
 42 
 43       return  ret;
 44  }
 45 
 46  int  search_infile( char *  szfile)
 47  {
 48       int  ret  =   - 1 ;
 49      
 50      FILE *     file  =  fopen(szfile,  " r " );
 51       char *      line  =  NULL;
 52 
 53       if (file  !=  NULL)
 54      {
 55           int  n  =   0 ;
 56          size_t size;
 57           while (getline( & line,  & size, file)  !=   - 1 )
 58          {
 59              search_inline(szfile, line, n);
 60              n ++ ;
 61          }
 62 
 63          free(line);
 64          fclose(file);
 65      }
 66  #ifdef _DEBUG
 67       else
 68      {
 69          printf( " open file \'%s\' failed!%s\n " , szfile, strerror(errno));
 70      }
 71  #endif
 72       return  ret;
 73  }
 74 
 75  int  search_indir( char *  dir)
 76  {
 77       struct  dirent **  namelist;
 78       int  n  =  scandir(dir,  & namelist,  0 0 );
 79       if (n  <   0 )
 80      {
 81          perror( " error in scandir\n " );
 82           return   - 1 ;
 83      }
 84      
 85       while (n -- )
 86      {
 87           if (strcmp( " . " , namelist[n] -> d_name) ==   0
 88           || strcmp( " .. " , namelist[n] -> d_name)  ==   0 )
 89          {
 90               // printf("ignored!%s\n", namelist[n]->d_name);
 91               continue ;
 92          }
 93 
 94           char  szTemp[ 512 =  { 0 };
 95          sprintf(szTemp,  " %s/%s " , dir, namelist[n] -> d_name);
 96           // printf("searching:%s\n", szTemp);        
 97 
 98           if (namelist[n] -> d_type  ==  DT_REG)
 99          {
100              search_infile(szTemp);
101          }
102           else   if (namelist[n] -> d_type  ==  DT_DIR)
103          {
104              search_indir(szTemp);
105          }
106          free(namelist[n]);
107      }
108      free(namelist);
109  }
110 
111  int  main( int  argc,  void **  argv)
112  {
113       if (argc  <   3 )
114      {
115          USAGE;
116      }
117 
118      strcpy(szBase, argv[ 1 ]);
119      
120       // keyworks fromat: -'KEY WORDS', will search KEY WORDS
121       if ((strncmp(argv[ 2 ],  " \' " 2 ==   0 &&  (strlen(argv[ 2 ])  >   3 ))
122      {
123           char *  p  =  argv[ 2 +   2 ;
124          strncpy(szKey, p, strlen(p) - 1 );
125          printf( " searching:%s\n " , szKey);
126      }
127       else
128      {
129          strcpy(szKey, argv[ 2 ]);
130      }
131 
132      search_indir(szBase);
133          
134       return   0 ;
135  }

 

示例:

linux c 文件内容搜索小工具




update:

增加选项:

-i 排除指定文件(文件夹)

-type 只搜索指定类型(后缀)的文件

均支持','分隔

#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <iostream>
#define _DEBUG

#define USAGE printf("usage:\e[1mxsearch\e[0m \e[4mDIRECTORY\e[0m \e[4mKEYWORDS\e[0m \e[4m-i IGNORE\e[0m\n"); return -1;

static char szBase[512] = {0};
static char szKey[512] = {0};

char** g_ignore_list = NULL;
int g_ignore_list_size = 0;

char** g_file_type_list = NULL;
int g_file_type_list_size = 0;

int search_inline(char* file, char* line, int nline)
{
    int ret = -1;
    
    char* p = strstr(line, szKey);
    if(p == NULL)
    {
        return ret;
    }
    //printf("\e[34m[%s-%d]\e[0m%s", file, nline+1, line);
    printf("\e[34m\e[1m[%s:%d]\e[0m", file, nline+1);
    
    char* pTemp = line;
    char* pTail = (p + strlen(szKey));
    while(p)
    {
        while(pTemp != p)
        {
            printf("%c", *pTemp);
            pTemp ++;
        }
        printf("\e[31m\e[1m%s\e[0m", szKey);
        
        p += strlen(szKey);
        pTail = pTemp = p;

        p = strstr(p, szKey);
    }
	//TODO if pTail contains some format string, such as ", \ %u, %d, might got SIGSEGV
    //printf(pTail);
	std::cout<<pTail;
    return ret;
}

bool check_file_type(const char* name)
{
	if(g_file_type_list_size == 0)
	{
		return true;
	}
	
	//get file type
	size_t _len = strlen(name);
	if(_len == 0)
	{
		return false;
	}

	const char* _p = name + _len - 1;
	while(_p != name)
	{
		if(*_p == '.')
		{
			break;
		}
		_p--;
	}	
	_p++;
	//printf("type:%s\n", _p);

        int i=0;
        for(;i<g_file_type_list_size; i++)
        {
                if(g_file_type_list[i] && strcmp(g_file_type_list[i], _p) == 0)
                {
                        return true;
                }
        }
	

	return false;
}

bool check_ignore(const char* name)
{
	if(name == NULL)
	{
		return false;
	}

	int i=0;
	for(;i<g_ignore_list_size; i++)
	{
	        if(g_ignore_list[i] && strcmp(g_ignore_list[i], name) == 0)
		{
			return false;
		}
	}

	return true;
}

int search_infile(char* szfile)
{
	//printf("file:%s\n", szfile);
        if(check_file_type(szfile) == false)
        {
		//printf("XXXXXXXXXufcked.\n");
                return 0;
        }

    int ret = -1;

    FILE*    file = fopen(szfile, "r");
    char*     line = NULL;

    if(file != NULL)
    {
        int n = 0;
        size_t size;
        while(getline(&line, &size, file) != -1)
        {
            search_inline(szfile, line, n);
            n++;
        }

        free(line);
        fclose(file);
    }
#ifdef _DEBUG
    else
    {
        printf("open file \'%s\' failed!%s\n", szfile, strerror(errno));
    }
#endif
    return ret;
}

int search_indir(char* dir)
{
    struct dirent** namelist;
    int n = scandir(dir, &namelist, 0, 0);
    if(n < 0)
    {
        perror("error in scandir\n");
        return -1;
    }
    
    while(n--)
    {
        if(strcmp(".", namelist[n]->d_name)== 0
        ||strcmp("..", namelist[n]->d_name) == 0)
        {
            //printf("ignored!%s\n", namelist[n]->d_name);
            continue;
        }

	if(check_ignore(namelist[n]->d_name) == false)
	{
		continue;
	}

        char szTemp[512] = {0};
        sprintf(szTemp, "%s/%s", dir, namelist[n]->d_name);
        //printf("searching:%s\n", szTemp);        

        if(namelist[n]->d_type == DT_REG)
        {
            search_infile(szTemp);
        }
        else if(namelist[n]->d_type == DT_DIR)
        {
            search_indir(szTemp);
        }
        free(namelist[n]);
    }
    free(namelist);
}

char** split_param_list(const char* param, const char* delim, int* size)
{
	if(param == NULL || delim == NULL || size == NULL)
	{
		return NULL;
	}
	//printf("%s\n", param);

	char** list = NULL;
	int _len = strlen(param);
	*size = 0;

	int i=0;
	for(; i<_len; i++)
	{
		if(param[i] == *delim)
		{
			(*size)++;
		}
	}	
	(*size)++;

	list = (char**)malloc(*size);

	int _count = 0;
	const char* _start=param;
	for(i=0; i<_len; i++)
	{
		if(param[i] == *delim)
		{
			const char* _p = param + i;
			if(_p-_start == 0)
			{
				_start++;
				continue;
			}

			list[_count] = (char*)malloc(_p-_start);
			strncpy(list[_count], _start, _p-_start);
			
			_start = ++_p;
			_count++;
		}
	}
	
	if(*_start != *delim)
	{
		const char* _p = param + i;
                list[_count] = (char*)malloc(_p-_start);
                strncpy(list[_count], _start, _p-_start);
	}

	//dump
	/*for(i=0; i<*size; i++)
	{
		printf("%s\n", list[i]);
	}
	*/
	return list;
}

void test()
{
	split_param_list("sdvs,gdfa,cd,a232,fuck",",", &g_ignore_list_size);
	exit(0);
}

int main(int argc, char** argv)
{
	//test();

    if(argc < 3)
    {
        USAGE;
    }

    strcpy(szBase, argv[1]);
    
    //keyworks fromat: -'KEY WORDS', will search KEY WORDS
    if((strncmp(argv[2], "\'", 2) == 0) && (strlen(argv[2]) > 3))
    {
        char* p = argv[2] + 2;
        strncpy(szKey, p, strlen(p)-1);
        printf("searching:%s\n", szKey);
    }
    else
    {
        strcpy(szKey, argv[2]);
    }

	
	if(argc > 3)
	{
		for(int i=3; i<argc; i++)
		{
			if(strcmp("-i", argv[i]) == 0)
			{
				if(i == argc -1)
				{
					USAGE;
				}
				g_ignore_list =	split_param_list(argv[++i], ",", &g_ignore_list_size);
			}
			else if(strcmp("-type", argv[i]) == 0)
			{                           
				if(i == argc -1)
                                {
                                        USAGE;
                                }
				g_file_type_list = split_param_list(argv[++i], ",", &g_file_type_list_size);
				
			}
		}
	}

	printf("************************************************\n");
	if(g_file_type_list_size > 0)
	{
		printf("\n[file type]:\n");
		int i=0;
		for (;i<g_file_type_list_size; i++)	
		{
			printf("%s\n", g_file_type_list[i]);
		}
	}

        if(g_ignore_list_size > 0)
        {
                printf("\n[ignore]:\n");
                int i=0;
                for (;i<g_ignore_list_size; i++)
                {
                        printf("%s\n",g_ignore_list[i]);
                }
        }
	printf("************************************************\n");

    search_indir(szBase);
        
    return 0;
}