I had a weird requirement for a program I wrote recently in C, where I want to locate the first two files in a given directory that differ only by specified extensions. Obviously, this is quite bespoke, so there wasn’t anything really out there.
I came up with a nice solution and thought I would share it here for others to benefit from.
0001 #include <dirent.h> 0002 0003 /** 0004 * get_extension() 0005 * 0006 * Get a pointer to the extension of a filename string. 0007 * 0008 * @param fn The filename to be searched. Must be non-NULL. 0009 * @return The location of the file extension, otherwise the start of the 0010 * string. 0011 **/ 0012 char* get_extension(char* fn){ 0013 char* last = strrchr(fn, '.'); 0014 return last != NULL ? last + 1 : fn; 0015 }
The above is a helper function for locating an extension for a given filename string.
0016 /** 0017 * search_file_pair() 0018 * 0019 * Find the first two files with the same name, that have the given extensions 0020 * for a requested path. 0021 * 0022 * @param path The path to be searched. 0023 * @param ext_a The first extension. 0024 * @param ext_b The second extensions. 0025 * @return The name of the file found, otherwise NULL. You must free() this 0026 * after use. 0027 **/ 0028 char* search_file_pair(char* path, char* ext_a, char* ext_b){ 0029 /* Make sure ext_a is longer than ext_b */ 0030 if(strlen(ext_a) < strlen(ext_b)){ 0031 char* t = ext_a; 0032 ext_a = ext_b; 0033 ext_b = t; 0034 } 0035 DIR* d; 0036 struct dirent* dir; 0037 d = opendir(path); 0038 /* Check we opened the directory */ 0039 if(d){ 0040 /* Loop over all entries in the directory */ 0041 while((dir = readdir(d)) != NULL){ 0042 /* Ensure this is not a directory */ 0043 if(dir->d_type != DT_DIR){ 0044 /* Do we have a match on the first extension? */ 0045 char* ext = get_extension(dir->d_name); 0046 if(strcmp(ext_a, ext) == 0 && dir->d_name != ext){ 0047 /* Build expected pair file with path used to find other file */ 0048 /* Length: Path + / + file + extension + NULL terminator */ 0049 char* fn = (char*)malloc(sizeof(char) * (strlen(path) + 1 + strlen(dir->d_name) + 1)); 0050 strcpy(fn, path); 0051 strcpy(fn + strlen(fn), "/"); 0052 strcpy(fn + strlen(fn), dir->d_name); 0053 strcpy(get_extension(fn), ext_b); 0054 /* Check if we found a pair */ 0055 if(access(fn, F_OK) == 0){ 0056 /* Remove the extension we just added */ 0057 *(get_extension(fn) - 1) = '\0'; 0058 return fn; 0059 }else free(fn); 0060 } 0061 } 0062 } 0063 /* Close the file */ 0064 close(d); 0065 } 0066 return NULL; 0067 }
And that was the magic function. It could in theory be a little faster, but it also needs to be memory efficient too for this use-case.
Anyway, I hope to be able to share what this is about soon…