I'm trying to make a C program that will display all the files and folders containing a given search term. The search term is given as an argument when executing the program. A folder / file is displayed to standard output if its name contains the search term (case insensitive). The difficulty though is that I do not want to output files and subfolders that are contained in a folder that contains the search term. Here's an example:
Let's assume my search term is docker, this is the current output:
"/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"
But this is the output I'm trying to achieve:
"/Users/me/.docker"
"/Users/me/Library/Application Support/Docker Desktop"
Here's my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
static int display_info(const char *fpath, const char * fname, const char * term) {
int what_len = strlen(term);
int count = 0;
char *where = fpath;
if (what_len){
while ((where = strcasestr(where, term))) {
where += what_len;
count++;
}
if (count == 1) {
printf("\"%s/%s\"\n", fpath, fname);
}
}
return 0;
}
static void listFilesRecursively(char * basePath, const char * searchTerm) {
char path[1000];
struct dirent * dp;
DIR * dir = opendir(basePath);
// Unable to open directory stream
if (!dir)
return;
while ((dp = readdir(dir)) != NULL) {
if (strcmp(dp -> d_name, ".") != 0 && strcmp(dp -> d_name, "..") != 0) {
// printf("%s %hhu %s\n", basePath, dp->d_type, dp -> d_name);
display_info(basePath, dp->d_name, searchTerm);
// Construct new path from our base path
strcpy(path, basePath);
strcat(path, "/");
strcat(path, dp -> d_name);
listFilesRecursively(path, searchTerm);
}
}
closedir(dir);
}
int main(int argc, const char * argv[]) {
char * home = getenv("HOME");
if (argc == 2) {
listFilesRecursively(home, argv[1]);
} else {
printf("Please provide one argument");
}
return 0;
}
Any feedback is greatly appreciated thanks!
display_info()
listFilesRecursively()
you can not reusepath
from call to callmain()
should the the first function in your code, maybe in a separate filean alternative
I will add a C example, changing a bit of your
listFilesRecursively()
....
and..
at the beginning of the loop and just usingcontinue
may lead into code easier to readpath
is allocated locally andfree()
on returnstrstr_ign()
is a case insensitive version ofstrstr()
for use in the pattern searchcode for
list_files()
after changecode for
strstr_ign()
I hate the arguments order for
strstr()
but kept it here just to have things equal. This way one can usestrstr_ign()
as a drop-in replacement forstrstr()
without changing the order of the arguments. I believeneedle
should come first :) an in the language: search for a needle in a haystack is far more common than search the haystack for a needle but Ken and Dennis had their reasons to writestrstr()
the way they did it...a new
display_info()
changed to show last access for folders and file size for regular files that match the search pattern (case insensitive). Below is an example of the output for files and folders. Note the '-' and the 'd' as in the
ls -l
output.sample output
C code for this test
miminally tested :)