Originally Posted By: peter
Unless the US list of not-capitalised words is written somewhere so definitively that changing it requires large majorities in both Houses of Congress and ratification by all the states, I'd recommend capitalising everything. Part of the reason you're capitalising in the first place is (presumably) to canonicalise the names and avoid ambiguity -- ambiguity which roars back again if there's any disagreement about the list of uncapitalised words.

Agreed.

But just in case, here's the deluxe model, which leaves 1,2,3 letter file extensions alone, as well having an internal list of other words to not touch (eg. the, of, and ..)

This is now a standalone gawk script, rather than being wrapped in a shell script as before, and can now handle (leaving alone) leading directories in the names:
Code:
#!/usr/bin/gawk -f
function rename_file(path, old_name  ,space,dquote,backslash,nlw,lw,new_name,i,in_word,w,tail,c,rename)
{
        space = " "             ## a space character
        dquote = "\""           ## a double-quote character
        backslash = "\\"        ## a backslash character
        max_extension = 4       ## length of .xxx file extensions to not touch

        ## Words to not captitalize:
        lowercase_words = "the of and a is flac"

        nlw = split(lowercase_words,lw," ");

        ## Insert backslashes in front of any " characters inside the file name,
        ## so that they are preserved when we later invoke system() on it:
        gsub(dquote, backslash dquote, old_name)

        ## Copy old_name to new_name, and capitalize first letters of all words:
        in_word = 0
        new_name = ""
        for (i = 1; i <= length(old_name); ++i) {
                tail = substr(old_name,i)

                ## Leave 1/2/3 character file extensions untouched:
                if (length(tail) <= max_extension && tail ~ "^[.][a-zA-Z0-9]*$") {
                        new_name = new_name tail
                        break;
                }
                c = substr(tail,1,1)

                ## Leave "lowercase_words" untouched:
                for (w = 1; w <= nlw; ++w) {
                        if (tail" " ~ "^" lw[w] "[^a-zA-Z]") {
                                in_word = 1;
                                break;
                        }
                }

                ## Capitalize anything else:
                if (c !~ "[a-zA-Z]") {
                        in_word = 0
                } else if (in_word == 0) {
                        in_word = 1
                        c = toupper(c)
                }
                new_name = new_name c
        }

        ## If new_name differs from old_name, then rename the file:
        if (new_name != old_name) {
                ## Issue a command to rename the file:
                rename = "/bin/mv"
                print rename space dquote path old_name dquote space dquote path new_name dquote
                system(rename space dquote path old_name dquote space dquote path new_name dquote)
        }
}

BEGIN {
        ## Command line arguments are files to rename
        for (a = 1; a < ARGC; ++a) {
                path = ARGV[a]
                ## Split path into directories + filename:
                if (1 == match(path,"^(.*/)([^/]*$)",p))
                        rename_file(p[1],p[2])
                else
                        rename_file("",path)
        }
        exit(0);
}