#include #include #include #include static const char** filters = NULL; static int filterAmount = 0; static char path[PATH_MAX] = {'\0'}; static int pathLength = 0; typedef struct { char path[PATH_MAX]; int lines; } LineFile; static LineFile* lineFiles = NULL; static size_t lineFileIndex = 0; static size_t lineFileCapacity = 0; static void addLineFile(int lines) { while(lineFileIndex >= lineFileCapacity) { lineFileCapacity += 16; lineFiles = realloc(lineFiles, sizeof(LineFile) * lineFileCapacity); } LineFile* lf = lineFiles + lineFileIndex++; memcpy(lf->path, path, sizeof(path)); lf->lines = lines; } static void appendToPath(const char* s) { for(int i = 0; pathLength < (PATH_MAX - 1) && s[i] != '\0'; i++) { path[pathLength++] = s[i]; } path[pathLength] = '\0'; } static int enterPath(const char* name) { int length = pathLength; appendToPath("/"); appendToPath(name); return length; } static void resetPath(int marker) { path[marker] = '\0'; pathLength = marker; } static void countLines(void) { FILE* file = fopen(path, "r"); if(file == NULL) { return; } int lines = 0; while(1) { int c = fgetc(file); if(c == EOF) { lines++; break; } else if(c == '\n') { lines++; } } addLineFile(lines); fclose(file); } static void handleFile(const char* name) { size_t end = strlen(name); for(int i = 0; i < filterAmount; i++) { if(*filters[i] == '-') { continue; } size_t l = strlen(filters[i]); if(end >= l && !strcmp(filters[i], name + (end - l))) { int marker = enterPath(name); countLines(); resetPath(marker); return; } } } static int isAllowedName(const char* name) { for(int i = 0; i < filterAmount; i++) { if(*filters[i] != '-') { continue; } if(!strcmp(name, filters[i] + 1)) { return 0; } } return 1; } static void scanFolder(void) { DIR* dir = opendir(path); if(dir == NULL) { return; } while(1) { struct dirent* entry = readdir(dir); if(entry == NULL) { break; } else if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { continue; } else if(entry->d_type == DT_DIR) { const char* name = entry->d_name; if(isAllowedName(name)) { int marker = enterPath(name); scanFolder(); resetPath(marker); } } else if(entry->d_type == DT_REG) { handleFile(entry->d_name); } } closedir(dir); } static int compareLineFiles(const void* a, const void* b) { const LineFile* lnA = a; const LineFile* lnB = b; if(lnA->lines < lnB->lines) { return -1; } return lnA->lines == lnB->lines ? 0 : 1; } int main(int argAmount, const char** args) { if(argAmount < 3) { puts("Use '-' before a name to exclude such paths"); if(argAmount > 0) { printf("%s [ending_2] ...\n", args[0]); } else { puts("... [ending_2] ..."); } return 0; } filters = args + 2; filterAmount = argAmount - 2; appendToPath(args[1]); scanFolder(); qsort(lineFiles, lineFileIndex, sizeof(LineFile), compareLineFiles); int allLines = 0; for(size_t i = 0; i < lineFileIndex; i++) { LineFile* ln = lineFiles + i; printf("%6d | %s\n", ln->lines, ln->path); allLines += ln->lines; } printf("Lines: %d\n", allLines); free(lineFiles); return 0; }