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 */