This works for me. There is probably a neater way of doing it in PERL. I made it case-independent because it was The Right Thing(tm) to do, and ``-lo-!'' two of the RPMs (DrakProfile and DrakSync) had changed from dual-case to lowercase during mirroring. I don't know if that's how it's supposed to be. -- The Chico, California, City Council enacted a ban on nuclear weapons, setting a $500 fine for anyone detonating one within city limits.
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #define FREE(pointer) /* nothing: waste of CPU for a one-shot program */ void printname (char * name, int len) { printf ("%s-%s\n", name, name + len); } int main (int argc, char * * argv) { int chosen1, scan1, scan2, scanlen; long n1, n2; char * candidate, * competitor; if (argc < 2) { printf ("Useage: %s file(s)\n" "I pick the latest versions of RPM files and print the\n" "names of losers. Typical invokation (BASH style) is:\n\n" " rm -f $(oldrpms *.rpm)\n", * argv); exit (1); } /* pass 1: eliminate non-RPMs, reduce all names to base names by chopping at the second-last hyphen, leaving the tail behind for later comparisons */ // fprintf (stderr, "#nonRPMs#\n"); for (chosen1 = 1; chosen1 < argc; ++ chosen1) { if (strcasecmp (".rpm", argv[chosen1] + strlen (argv[chosen1]) - 4)) { // fprintf (stderr, "#notRPM#%s\n", argv[chosen1]); printf ("%s\n", argv[chosen1]); FREE (argv[chosen1]); argv[chosen1] = NULL; continue; } candidate = strrchr (argv[chosen1], '-'); if (candidate != NULL && candidate != argv[chosen1]) { competitor = candidate; * competitor = '\0'; candidate = strrchr (argv[chosen1], '-'); * competitor = '-'; } if (candidate == NULL) { /* not a systematic RPM name */ // fprintf (stderr, "#notSystematic#%s\n", argv[chosen1]); printf ("%s\n", argv[chosen1]); FREE (argv[chosen1]); argv[chosen1] = NULL; continue; } * candidate = '\0'; } /* pass 2: compare basenames for duplicates, eliminate singletons, compare tails of any remaining names and print/delete older of each pair */ // fprintf (stderr, "#dupes#\n"); for (chosen1 = 1; chosen1 < argc; ++ chosen1) { // fprintf (stderr, "# %d%%\r", chosen1 * 100 / argc); if (argv[chosen1] == NULL) continue; scan1 = chosen1; scanlen = strlen (argv[chosen1]) + 1; for (scan2 = 1; scan2 < argc; ++ scan2) { if (scan2 == scan1) continue; if (argv[scan2] == NULL) continue; if (strcasecmp (argv[scan1], argv[scan2])) continue; candidate = argv [scan1] + scanlen; competitor = argv [scan2] + scanlen; while (* candidate && * competitor) { if (isdigit (* candidate) && isdigit (* competitor)) { n1 = strtol (candidate, & candidate, 10); n2 = strtol (competitor, & competitor, 10); if (n1 > n2) { printname (argv[scan2], scanlen); FREE (argv[scan1]); argv[scan2] = NULL; break; } if (n1 < n2) { printname (argv[scan1], scanlen); FREE (argv[scan1]); argv[scan1] = NULL; scan1 = scan2; break; } } else { /* not both numbers */ if (tolower (* candidate) > tolower (* competitor)) { printname (argv[scan2], scanlen); FREE (argv[scan1]); argv[scan2] = NULL; break; } if (tolower (* candidate) < tolower (* competitor)) { printname (argv[scan1], scanlen); FREE (argv[scan1]); argv[scan1] = NULL; scan1 = scan2; break; } ++ candidate; ++ competitor; } } /* compare to end or difference */ } } // for (chosen1 = 1; chosen1 < argc; ++ chosen1) { // if (argv[chosen1] != NULL) { // argv[chosen1][strlen (argv[chosen1])] = '-'; // fprintf (stderr, "#kept#%s\n", argv[chosen1]); // } // } exit (0); } /* end */