Converting filenames to Title Case in Linux

by @edent | # # | 11 comments | Read ~1,403 times.

Here's a simple bash one-liner to convert mixed-case filenames into Title Case:

rename 's/(\S+)/\u\L$1/g' *

This forces the file extension to lower-case as well.

Use rename -n to test the command without changing anything on the filesystem.

(Adapted from this PerlMonks FAQ.)

Background

I have a bunch of inconsistently named files like:

HERE COMES THE SUN.mp3
hey jude.mp3
The lOng and wiNDing Road.mp3

I want them to appear as:

Here Comes The Sun.mp3
Hey Jude.mp3
The Long And Winding Road.mp3

Two Line Approach

First, rename all files to lower-case:

rename 'y/A-Z/a-z/' *

Second, make the first letter of each word Upper Case:

rename 's/(^|[\s_-])([a-z])/$1\u$2/g' *

11 thoughts on “Converting filenames to Title Case in Linux

  1. mike says:

    You didn't remove the spaces! What sort of monster are you!? 😉

    I like the rename command though. Years of poking around *nix and I didn't recall ever encountering it. I would have used to mv and an argument involving tr to convert lowercase.

    $ echo "The lOng and wiNDing Road.mp3" | tr [:upper:] [:lower:]
    the long and winding road.mp3

  2. Exceptions of course ...
    Old MacDonald Had A Farm
    and for fun ... try one towards the end of
    http://www.dandelionradio.com/tracklists/2012-01/

    I was discussing same sort of thing recently - see posts about 5 down
    http://forums.slimdevices.com/archive/index.php/t-106900.html

    1. Terence Eden says:

      Yes, tricky with non-ASCII characters.

  3. Heretic! That should be:

    Here Comes the Sun.mp3
    Hey Jude.mp3
    The Long and Winding Road.mp3

    Friendships have ended over less 😉

  4. Arthur says:
    #!/bin/bash
    
    for file in * ; do
        words=("$file")
        title=""
        wc=0
        for word in $words ; do
        first=$(echo $word | cut -c1 | tr ‘[[:lower:]]’ ‘[[:upper:]]’)
        others=$(echo $word | cut -c2-)
        word="$first$others"
        for prep in {The,A,An,As,At,But,By,For,In,Of,Off,On,Per,To,Up,Via,And,Nor,Or,So,Yet,With}
        do
            if [[ $wc -gt 0 ]] ; then
            if [[ "$word" == "$prep" ]] ; then
                word=`echo "$word" | tr '[A-Z]' '[a-z]'`
            fi
            fi
        done
        title="$title$word"
        title="$title "
        wc=$(($wc + 1))
        done
        #echo "$title"
        mv -- "$file" "$title" > /dev/null 2>&1
    done
    

    One thing it DOES NOT do is capitalize last word if it is a preposition which seems to be the rule in all three title case schools (Chicago, MLA and AP), but this does the job in probably 95%~99% cases.

  5. Adrian says:

    One line approach 🙂

    rename -E 'y/A-Z/a-z/' -E 's/(^|[\s_-])([a-z])/$1\u$2/g' *

  6. jamisan says:

    elegant and simple. reminds me of an old unix bud of mine (god rest his soul). he said, i just love when I can write a one line program with a string of text and a couple of alt-shift-left-elbows. thanks terence. p.s. how can i find if you have other similar gems buried in your blogs?

    1. @edent says:

      Thanks! You'll find most of them at https://shkspr.mobi/blog/tag/linux/

  7. Alan says:

    Hi Guys,

    I used the suggestion from XX above:

    rename -E 'y/A-Z/a-z/' -E 's/(^|[\s_-])([a-z])/$1\u$2/g' *

    This works great, except - it lowercases (if I can invent a word) a letter in the middle of a text string containing numbers such as:

    CoMpany - X01B02 - LETTER.txt

    becomes:

    Company - X01b02 - Letter.txt

    Is there any way top amend that one line command to avoid the 'B' in the middle of the reference getting changed to 'b' so that, instead, it comes out as:

    Company - X01B02 - Letter.txt

    I am guessing we need to look for a letter, not being the first character of a word, sandwiched between two numerals, but by RegExp fu is just not up to it!

    If it helps, we can assume it is only ever a single letter with a numeral immediately left and right of it.

    Thanks,

    Alan.

  8. CpILL says:

    The first command doesn't work for me on Ubuntu 18.04 for some reason. Here is what it says for one file:

    0003 BEYOND BAROQUE.mp3 not renamed: 0003 beyond baroque.mp3 already exists

    ?

    1. @edent says:

      It works on 19.04 - perhaps try updating?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.