// 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)
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment