Recursive String Search
Here is another one of those simple programs that are missing on the Windows platform; a functioning string search tool! The program's scheme is somewhat similar to using the UNIX grep command's combination of the '-n' '-i' and '-r' switches. It will search in a directory and it's sub-directories for a fixed case-insensitive string and display the name of each file, the line number and the line itself where that string is found.
Here's is a link to the binary for Win32 (compiled with MinGW) and here's the source code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>
static char line[1024];
static void recurse(char *path, char *string, int len)
{
char full_path[PATH_MAX];
int n, match, name_shown, line_no;
struct dirent *entry;
struct stat st;
DIR *dh;
FILE *fh;
dh = opendir(path);
if (dh == NULL) {
fprintf(stderr, "Warning: Unable to open directory: %s\n", path);
return;
}
while ((entry = readdir(dh))) {
if (entry->d_name[0] == '.')
continue; /* Ignore files with leading dot. */
#ifdef WINNT
snprintf(full_path, PATH_MAX, "%s\\%s", path, entry->d_name);
#else
snprintf(full_path, PATH_MAX, "%s/%s", path, entry->d_name);
#endif
stat(full_path, &st);
if (S_ISDIR(st.st_mode)) {
/* Traverse. */
recurse(full_path, string, len);
} else if (S_ISREG(st.st_mode)) {
/* Search. */
fh = fopen(full_path, "r");
if (fh == NULL) {
fprintf(stderr, "Warning: Unable to open file: %s\n", full_path);
continue;
}
name_shown = line_no = 0;
while (fgets(line, 1024, fh) != NULL) {
line_no++;
match = 0;
for (n = 0; line[n] != '\0'; n++) {
if (toupper(line[n]) == toupper(string[match])) {
match++;
if (match >= len) {
if (! name_shown) {
printf("%s\n", full_path);
name_shown = 1;
}
printf("%d:%s", line_no, line);
break;
}
} else {
match = 0;
}
}
}
fclose(fh);
}
}
closedir(dh);
return;
}
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr, "Usage: %s <directory> <string>\n", argv[0]);
return 1;
}
recurse(argv[1], argv[2], strlen(argv[2]));
return 0;
}