// TSUNAMI - Text Search Utility
//--------------------
// Searches files for multiple text strings
//
// - Takes up to 10 search strings
// - Searches up to 10 file types
// - Accepts wildcards (*, ?) in file types
// - Optionally searches subdirectories
// - Optionally searches hidden files/directories
// - Program can be paused or aborted early
// - Handles both text and binary files
// - All search strings must be found in file
// - Writes search results (file name and path) to
// TSUNAMI.OUT in current working directory
//
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <string.h>
const MAX_STRING = 512;
const MAX_LIST = 10;
const MAX_FNAME = 13; // max. field length for file types
const MAX_SSTR = 64; // max. field length for search strings
struct ft_list {
char array[MAX_LIST][MAX_FNAME];
int count;
};
struct ss_list {
char array[MAX_LIST][MAX_SSTR];
int count;
};
struct ft_list FLIST; // stores file types to search in
struct ss_list SLIST; // stores strings to search for
char SRCH_DIR[MAX_STRING];
char ORIG_DIR[MAX_STRING];
const YES = 1;
const NO = 0;
int DO_SUBDIRS;
int DO_HIDDEN;
int DO_OPTIMIZE;
int RESULTS_COUNT = 0;
char RESULTS_FILE[MAX_FNAME] = "TSUNAMI.OUT"; // output file
FILE *results_fptr;
//--------------------------------------------------------
void pause (void)
{
printf("\nPress any key... \n");
while (!kbhit());
}
//-----------------------------
int file_exist (const char *fname)
{
struct ffblk ffblk;
return(findfirst(fname, &ffblk, FA_DIREC+FA_HIDDEN));
}
//--------------------------------------------------------
char *upstr (char *s)
{
int i;
for (i = 0; s[i] != 0; i++) s[i] = toupper(s[i]);
return (s);
} // upstr
//--------------------------------------------------------
int get_ext_key (char k)
{
if (k == 0) k = getch();
return (k);
} // get_ext_key
//--------------------------------------------------------
char *get_input (char *s, int max_len)
// s is the default input string to display
// max_len is the maximum length for input + 1
// length of s MUST be <= max_len <= MAX_STRING
{
char t[MAX_STRING] = {'\0'};
int i, key;
if (max_len > MAX_STRING) max_len = MAX_STRING; // keep in range
strcpy(t, s);
i = strlen(s);
printf("%s", s);
while (!kbhit())
{
switch(key = getch())
{
case 0: // EXTENDED KEY
{
key = get_ext_key(key);
break;
}
case 8: // BACKSPACE
{
if (i > 0)
{
putch(key);
putch(' ');
putch(key);
t[--i] = '\0';
}
break;
}
case 13: // RETURN
{
putch('\n');
putch(key);
strcpy(s, t);
return(s);
}
case 27: // ESCAPE
{
putch('\n');
putch('\r');
s = "";
return(s);
}
default:
{
if (i < max_len-1) // allow for ending null
{
putch(key);
t[i] = key;
i++;
t[i] = '\0';
break;
}
}
}
}
return (s);
} // get_input
//--------------------------------------------------------
void user_interrupt (void)
{
int key = 0;
switch (key = (int) toupper(getch()))
{
case 'P': // PAUSE
{
printf("\rPausing. Press any key to continue...");
clreol();
while (!kbhit());
break;
}
case 27: // ESCAPE
{
printf("\rAborting TSUNAMI");
clreol();
printf("\n\n%d results saved in %s\n", RESULTS_COUNT, RESULTS_FILE);
chdir(ORIG_DIR);
exit(1);
}
default:
{
}
}
} // user_interrupt
//--------------------------------------------------------
void input_search_directory (void)
{
char s[MAX_STRING] = {'\0'};
strcpy(s, "C:\\DOCUME~1\\ADMINI~1\\MYDOCU~1\\DOWNLO~1");
printf("Specify directory to search in:\n");
do
{
strcpy(SRCH_DIR, upstr(get_input(s, MAX_STRING)));
if (SRCH_DIR[0] == '\0')
{
printf("\nAborting TSUNAMI...\n");
exit(1);
}
if (SRCH_DIR[strlen(SRCH_DIR)-1] == '\\')
SRCH_DIR[strlen(SRCH_DIR)-1] = '\0';
if (file_exist(SRCH_DIR) != 0)
printf("\nERROR: Directory does not exist. Try again:\n");
strcpy(s, "");
}
while (file_exist(SRCH_DIR) != 0);
} // input_search_directory
//--------------------------------------------------------
int toggle_YN (char *s)
{
char ch;
printf("%s", s);
do
ch = toupper(getch());
while ((ch != 'Y') && (ch != 'N'));
printf("%c\n", ch);
if (ch == 'Y') return(YES); else return(NO);
} // toggle_YN
//--------------------------------------------------------
void input_search_strings (void)
{
char s[MAX_SSTR] = {'\0'};
SLIST.count = 0;
printf("Specify search strings (max. 10):\n");
while (SLIST.count < MAX_LIST)
{
strcpy(s, "");
printf("%d) ", SLIST.count+1);
strcpy(s, get_input(s, MAX_SSTR));
if (s[0] == '\0') break;
strcpy(SLIST.array[SLIST.count], s);
SLIST.count++;
}
} // input_search_strings
//--------------------------------------------------------
void input_file_strings (void)
{
char s[MAX_FNAME] = {'\0'};
FLIST.count = 0;
printf("Specify file types to search for (max. 10):\n");
while (FLIST.count < MAX_LIST)
{
strcpy(s, "*.*");
printf("%d) ", FLIST.count+1);
strcpy(s, upstr(get_input(s, MAX_FNAME)));
if (s[0] == '\0') break;
strcpy(FLIST.array[FLIST.count], s);
FLIST.count++;
}
} // input_file_strings
//--------------------------------------------------------
int search_file_for_string (char *fname, char *s)
{
FILE *fptr;
struct ffblk ffblk;
char ch;
int len;
int si = 0; // search string index
long fi = 0; // file index
len = strlen(s);
if ((fptr = fopen(fname, "rb")) != NULL)
{
findfirst(fname, &ffblk, FA_HIDDEN);
while (fi < ffblk.ff_fsize)
{
ch = fgetc(fptr);
fi++;
// convert special characters to spaces
if ((ch == '\n') || (ch == '\r') || (ch == '\t') || (ch == '\0'))
ch = ' ';
if ((ch == s[si]) && (si < len))
{
si++;
if (si == len)
{
fclose(fptr);
return(1);
}
}
else si = 0;
}
fclose(fptr);
}
return(0);
} // search_file_for_string
//--------------------------------------------------------
void save_results_to_file (char *fname)
{
char cwd[MAX_STRING] = {'\0'};
getcwd(cwd, MAX_STRING);
if (cwd[3] != '\0') strcat(cwd, "\\");
fprintf(results_fptr, "%s%s\n", cwd, fname);
if (!DO_OPTIMIZE) printf("\n");
} // save_results_to_file
//--------------------------------------------------------
void search_for_strings (char *fname)
{
int i, n;
n = 0;
for (i = 0; i < SLIST.count; i++)
{
if (search_file_for_string(fname, SLIST.array[i]) == 0) break;
if (kbhit()) user_interrupt(); // check for pause or abort
n++;
}
if ((n > 0) && (n == SLIST.count))
{
RESULTS_COUNT++;
save_results_to_file(fname);
}
} // search_for_strings
//--------------------------------------------------------
void search_for_files (char *fname)
{
struct ffblk ffblk;
char cwd[MAX_STRING] = {'\0'};
int att = 0;
int done;
getcwd(cwd, MAX_STRING);
if (cwd[3] != '\0') strcat(cwd, "\\");
if (DO_HIDDEN == YES) att = FA_HIDDEN;
done = findfirst(fname, &ffblk, att);
while (!done)
{
if (DO_OPTIMIZE == YES)
search_for_strings(ffblk.ff_name);
else
{
printf("\r%s%s", cwd, ffblk.ff_name);
clreol();
search_for_strings(ffblk.ff_name);
printf("\r");
clreol();
}
done = findnext(&ffblk);
}
if (DO_SUBDIRS == YES)
{
att = att + FA_DIREC;
done = findfirst("*.*", &ffblk, att);
while (!done)
{
if (ffblk.ff_attrib & FA_DIREC)
{
if (ffblk.ff_name[0] != '.')
{
chdir(ffblk.ff_name);
search_for_files(fname);
chdir("..");
}
}
done = findnext(&ffblk);
}
}
} // search_for_files
//--------------------------------------------------------
int main (void)
{
int i;
clrscr();
input_search_directory();
DO_SUBDIRS = toggle_YN("Search subdirectories? [Y/N]: ");
DO_HIDDEN = toggle_YN("Search hidden files/directories? [Y/N]: ");
DO_OPTIMIZE = toggle_YN("Full optimization (no screen output)? [Y/N]: ");
input_search_strings();
input_file_strings();
getcwd(ORIG_DIR, MAX_STRING);
if ((results_fptr = fopen(RESULTS_FILE, "wt")) != NULL)
{
chdir(SRCH_DIR);
printf("Press (P) to Pause, (ESC) to Abort...
for (i = 0; i < FLIST.count; i++)
search_for_files(FLIST.array[i]);
chdir(ORIG_DIR);
fclose(results_fptr);
printf("\n%d results in %s\n", RESULTS_COUNT, RESULTS_FILE);
pause();
}
return(0);
}
This blog is for novice C and C++ programmers who want to learn, share, and explore computer programming.
Wednesday, April 9, 2014
Updated Text Search Utility (Source Code)
Monday, April 7, 2014
My Text Search Utility
// TSUNAMI - Text Search Utility
// -----------------------------------
// Searches files for multiple text strings in given directory.
//
// - Takes up to 10 search strings
// - Searches up to 10 file types
// - Optionally searches subdirectories
// - Optionally searches hidden files/directories
// - Writes results to RESULTS.TMP in current working
// directory.
//
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <string.h>
const MAX_STRING = 1024;
const MAX_LIST = 10;
const MAX_FNAME = 13;
const MAX_SSTR = 64;
const YES = 1;
const NO = 0;
struct ft_list {
char array[MAX_LIST][MAX_FNAME];
int count;
};
struct ss_list {
char array[MAX_LIST][MAX_SSTR];
int count;
};
struct ft_list FLIST;
struct ss_list SLIST;
char RESULTS_FILE[MAX_FNAME] = "RESULTS.TMP";
char SRCH_DIR[MAX_STRING];
char ORIG_DIR[MAX_STRING];
int DO_SUBS;
int DO_HIDDEN;
FILE *results_fptr;
//--------------------------------------------------------
pause ()
{
printf("\nPress any key... \n");
while (!kbhit());
return(0);
}
//-----------------------------
int file_exist (const char *fname)
{
struct ffblk ffblk;
return(findfirst(fname, &ffblk, FA_DIREC+FA_HIDDEN));
}
//--------------------------------------------------------
char *upstr (char *s)
{
int i;
for (i = 0; s[i] != 0; i++) s[i] = toupper(s[i]);
return (s);
} // upstr
//--------------------------------------------------------
int get_ext_key (char k)
{
if (k == 0) k = getch();
return (k);
} // get_ext_key
//--------------------------------------------------------
char *get_input (char *s, int max_len)
{
char *t;
int i, key;
if ((t = (char *) malloc(MAX_STRING)) != NULL)
{
if (max_len <= MAX_STRING) strcpy(t, s);
i = strlen(t);
printf("%s", s);
while (!kbhit())
{
switch(key = getch())
{
case 0: // EXTENDED KEY
{
key = get_ext_key(key);
break;
}
case 8: // BACKSPACE
{
if (i > 0)
{
putch(key);
putch(' ');
putch(key);
t[--i] = '\0';
}
break;
}
case 13: // RETURN
{
putch('\n');
putch(key);
s = t;
return(s);
}
case 27: // ESCAPE
{
putch('\n');
putch('\r');
return(s);
}
default:
{
if (i < max_len)
{
putch(key);
t[i] = key;
i++;
t[i] = '\0';
break;
}
}
}
}
free(t);
}
return (s);
} // get_input
//--------------------------------------------------------
input_search_directory ()
{
struct ffblk ffblk;
char *s;
if ((s = (char *) malloc(MAX_STRING)) != NULL)
{
printf("Specify directory to search in:\n");
do
{
s = "";
strcpy(SRCH_DIR, upstr(get_input(s, MAX_STRING)));
if (SRCH_DIR[0] == '\0')
{
printf("\nAborting TSU...\n");
exit(1);
}
if (SRCH_DIR[strlen(SRCH_DIR)-1] == '\\')
SRCH_DIR[strlen(SRCH_DIR)-1] = '\0';
if (file_exist(SRCH_DIR) != 0)
printf("\nERROR: Directory does not exist. Try again:\n");
}
while (file_exist(SRCH_DIR) != 0);
free(s);
}
return (0);
} // input_search_directory
//--------------------------------------------------------
int toggle_subdirectories ()
{
char ch;
printf("Search subdirectories? [Y/N]: ");
do
ch = toupper(getch());
while ((ch != 'Y') && (ch != 'N'));
printf("%c\n", ch);
if (ch == 'Y') DO_SUBS = YES; else DO_SUBS = NO;
return (0);
} // toggle_subdirectories
//--------------------------------------------------------
int toggle_hidden ()
{
char ch;
printf("Search hidden files/directories? [Y/N]: ");
do
ch = toupper(getch());
while ((ch != 'Y') && (ch != 'N'));
printf("%c\n", ch);
if (ch == 'Y') DO_HIDDEN = YES; else DO_HIDDEN = NO;
return (0);
} // toggle_hidden
//--------------------------------------------------------
input_file_strings ()
{
char *s;
if ((s = (char *) malloc(MAX_FNAME)) != NULL)
{
s = "*.*";
FLIST.count = 0;
printf("Specify file types to search for (max. 10):\n");
while (FLIST.count < MAX_LIST)
{
printf("%d) ", FLIST.count+1);
s = upstr(get_input(s, MAX_FNAME));
strcpy(FLIST.array[FLIST.count], s);
if (FLIST.array[FLIST.count][0] == NULL) break;
FLIST.count++;
s = "";
}
free(s);
}
return (0);
} // input_file_strings
//--------------------------------------------------------
input_search_strings ()
{
char *s;
if ((s = (char *) malloc(MAX_SSTR)) != NULL)
{
SLIST.count = 0;
printf("Specify search strings (max. 10):\n");
while (SLIST.count < MAX_LIST)
{
printf("%d) ", SLIST.count+1);
s = "";
s = get_input(s, MAX_SSTR);
strcpy(SLIST.array[SLIST.count], s);
if (SLIST.array[SLIST.count][0] == NULL) break;
SLIST.count++;
}
free(s);
}
return (0);
} // input_search_strings
//--------------------------------------------------------
int search_file_for_string (char *fname, char *s)
{
struct ffblk ffblk;
char ch;
int i = 0;
int len;
FILE *fptr;
len = strlen(s);
if ((fptr = fopen(fname, "rt")) != NULL)
{
do
{
ch = fgetc(fptr);
// convert special characters to spaces
if ((ch == '\n') || (ch == '\r') || (ch == '\0')) ch = ' ';
if ((ch == s[i]) && (i < len))
{
i++;
if (i == len)
{
fclose(fptr);
return(1);
}
}
else i = 0;
}
while (ch != EOF);
fclose(fptr);
}
return(0);
} // search_file_for_string
//--------------------------------------------------------
save_results_to_file (char *fname)
{
char cwd[MAX_STRING];
getcwd(cwd, MAX_STRING);
if (cwd[3] != '\0') strcat(cwd, "\\");
fprintf(results_fptr, "%s%s\n", cwd, fname);
printf("\n");
return(0);
} // save_results_to_file
//--------------------------------------------------------
search_for_strings (char *fname)
{
int i, n;
char *cwd;
n = 0;
for (i = 0; i < SLIST.count; i++)
{
if (search_file_for_string(fname, SLIST.array[i]) == 0) break;
n++;
}
if ((n > 0) && (n == SLIST.count))
save_results_to_file(fname);
return(0);
} // search_for_strings
//--------------------------------------------------------
search_for_files (char *fname)
{
struct ffblk ffblk;
char cwd[MAX_STRING];
int att = 0;
int done;
getcwd(cwd, MAX_STRING);
if (cwd[3] != '\0') strcat(cwd, "\\");
if (DO_HIDDEN == YES) att = FA_HIDDEN;
done = findfirst(fname, &ffblk, att);
while (!done)
{
printf("\r%s%s", cwd, ffblk.ff_name);
clreol();
search_for_strings(ffblk.ff_name);
printf("\r");
clreol();
done = findnext(&ffblk);
}
if (DO_SUBS == YES)
{
att = att + FA_DIREC;
done = findfirst("*.*", &ffblk, att);
while (!done)
{
if (ffblk.ff_attrib & FA_DIREC)
{
if (ffblk.ff_name[0] != '.')
{
chdir(ffblk.ff_name);
search_for_files(fname);
chdir("..");
}
}
done = findnext(&ffblk);
}
}
return (0);
} // search_for_files
//--------------------------------------------------------
int main (void)
{
int i;
clrscr();
input_search_directory();
toggle_subdirectories();
toggle_hidden();
input_search_strings();
input_file_strings();
getcwd(ORIG_DIR, MAX_STRING);
if ((results_fptr = fopen(RESULTS_FILE, "wt")) != NULL)
{
if (chdir(SRCH_DIR) == 0)
{
for (i = 0; i < FLIST.count; i++)
search_for_files(FLIST.array[i]);
chdir(ORIG_DIR);
}
fclose(results_fptr);
pause();
}
return(0);
}
Subscribe to:
Comments (Atom)