7th February 2022

Mass Lowercasing of File Names

Task at hand: lowercase ca. half a million file names. The obvious solution would be to use the mv command together with tr to accomplish the job:

for i in A B C ...; do mv $i `echo $i | tr '[A-Z]' '[a-z]'`; done

Each file would spawn two processes: one for the tr and one for the mv itself. The echo command is a shell built-in. tr is not part of BusyBox, so BusyBox cannot be used to get rid of the process flood.

To avoid the masses of process creations, I created below simple C program instead:

/* Lower case multiple files, so we avoid unnecessary sub-processes
   Elmar Klausmeier, 31-Jan-2022
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int i, st=0;
    char *fn, fnLower[256], *p, *q;

    for (i=1; i<argc; ++i) {
        fn=p=argv[i], q=fnLower;
        while ((*q++ = tolower(*p++)) != '\0')
            ;
        if (strcmp(fn,fnLower) == 0) continue;
        if ((st = rename(fn,fnLower)) != 0) {
            printf("Cannot lowercase %s, code=%d, error %s\n",
                fn,st,strerror(st));
            break;
        }
    }

    return st;
}

Calling is thus:

multilc A B C ...

The limit of this is just the maximal number of bytes on the command line. This can be queried:

$ getconf ARG_MAX
2097152

The result is in bytes.

Also see Parallel Mass-File Processing.