You know, speaking of different formats this seems like a good time to share.

Here's a script that rips cds and converts them to MP3s exactly the way I like it. It will create the directory "Artist/Title" and fill it with approximately 192kbps-average VBR mp3s. Nothing special, but rather than find a little tool on the net I figured I'd write my own.

Save it in a file and type "python filename"


import os
import re
import sys
import string
import commands
import CDDB, DiscID

# Some buffers to hold information we'll need
artist = ""
title = ""
tracks = []
nullLookup = 0
startDir = os.getcwd()

# get a single character from STDIN
def getch ():
    # from ASPN
    import sys, tty, termios
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
        ch =
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

def queryCDDB():
    # get info from CD
    cdrom =
    disc_id = DiscID.disc_id(cdrom)

    # query CDDB
    (query_status, query_info) = CDDB.query(disc_id)


    # single match
    if query_status == 200:
        char = ""
        (read_status, read_info) =['category'], query_info['disc_id'])
        for i in range(disc_id[1]):
            print "Track %.02d: %s" % (i+1, read_info['TTITLE' + `i`])
        print "\nPress [Enter] to continue, 'q' to quit: "
        while char != '\r':
            char = getch()
            if char == 'q':
                print "\n"
            elif char == '\r':
                for i in range(disc_id[1]):
                    tracks.append("%.02d_____%s" % (i+1, read_info['TTITLE' + `i`]))
                s = re.match("(.+?)\s+/\s+(.+)", query_info['title'])
                global artist
                artist =
                global title
                title =

    # multiple matches
    elif query_status == 210 or query_status == 211:
        char = ""
        while char != '\r':
            entryString = ""
            print "Multiple CDDB Entries Found.\n"
            print "ID:\tArtist / Album\n"
            for i in range(len(query_info)):
                printStr = "%s:\t" % str(i)
                printStr += query_info[i]['title']
                print printStr
            print "\nEnter ID, and press 'Enter' to select this entry, or 'v' to view the track listing\n\n\
            eg. '0v' or '1[Enter]' or 'q' to quit\n"
            sys.stdout.write("Selection: ")
            char = ""
            # construct the id number...ignore everything except digits, "v", and "[Enter]"
            while ( char != 'v' and char != '\r' ):
                if re.match("^[0-9]$", char):
                    entryString += char
                elif re.match("^q$", char):
                    print "\n"
                char = getch()
            # immediately store a copy of the user's selected option and free char for later use
            option = char
            char = ""

            # do not permit null entries or invalid numbers
            if (entryString == "" or int(entryString) > len(query_info)-1):
            # regardless of whether "v" or "[Enter]" was pressed, print out the chosen album info 
            (read_status, read_info) =[int(entryString)]['category'],\
            print "\n"
            print query_info[int(entryString)]['title']+"\n"
            for i in range(disc_id[1]):
                print "Track %.02d: %s" % (i+1, read_info['TTITLE' + `i`])
            print "\nPress [Enter] to continue, 'q' to quit. "
            while ( char != "\r" ):
                char = getch()
                if char == 'q':

            # if the user selected the option to choose the specified track, grab the info
            if option == '\r':
                s = re.match("(.+?)\s+/\s+(.+)", query_info[int(entryString)]['title'])
                global artist
                artist =
                global title
                title =
                for i in range(disc_id[1]):
                    tracks.append("%.02d_____%s" % (i+1, read_info['TTITLE' + `i`]))
    elif query_status == 202 or query_status == 403:
        # no match found :(
        char = ""
        if query_status == 403:
            print "ERROR: Database entry is corrupt!  Cannot obtain disc info.\n"
        print "No matches found :(\n"
        print "Press [Enter] to continue or 'q' to quit"
        while char != '\r' and char != 'q':
            char = getch()
        if char == 'q':
        if char == '\r':
            global nullLookup,artist,title
            artist = "Unknown Artist"
            title = "Unknown Title"
            nullLookup = 1
    elif query_status == 409:
        raise RuntimeError, "ERROR: No handshake with CDDB server.  Possible client-side error.\n"


def ripTracks():
    # grab the output of cdparanoia query so that we can make sure we have the right number of tracks
    data = commands.getoutput("cdparanoia -Q")
    array  = string.split(data, "\n")
    i = 0
    # count the number of lines that start with a few spaces, and a number followed by a period...these are tracks
    for line in array:
        if re.match("\s+\d+\..+", line):
            i = i+1
    if i != len(tracks) and nullLookup == 0:
        raise RuntimeError, "Number of tracks on CD does not match CDDB info!\nCD: %s, CDDB: %s\n"\
        % (str(i),str(len(tracks)))
        # Numbers match up.  Create the destination directory and cwd to it
        if os.path.exists("%s/%s" % (artist,title)):
            print "Path '%s/%s' already exists!\n\nPress [Enter] to remove it, or 'q' to quit\n" % (artist,title)
            char = getch()
            if char == "\r":
                os.system("rm -rf \"%s\"" % artist)
            elif char == 'q':
        os.makedirs("%s/%s/%s" % (startDir,artist,title))
        os.chdir("%s/%s/%s" % (startDir,artist,title))
        # begin cd extraction
        print "Starting Extraction from CD...\n"
        syscall = os.system("cdparanoia -B --never-skip=40")
        if syscall != 0:
            raise RuntimeError, "cdparanoia returned non-zero exit status! %s" % syscall
def encodeMP3s():
    os.chdir("%s/%s/%s" % (startDir,artist,title))
    files = os.listdir(".")
    for file in files:
        s = re.match("track(\d+).cdda\.wav", file)
        trackNumberCD =
        #temporarily store the ##_____Title format in trackTitle
        if nullLookup == 1:
            trackTitle = str(trackNumberCD)+"_____Track"+str(trackNumberCD)
            trackTitle = tracks[int(trackNumberCD)-1]
        # ensure cdparanoia and cddb track numbers match
        # also extract actual trackTitle
        (trackNumberCDDB,trackTitle) = string.split(trackTitle, "_____")
        if trackNumberCDDB != trackNumberCD:
            raise RuntimeError, "CDDB track number: %s\nCD track number: %s\n" \
            % (tracknumberCDDB,tracknumberCD)
        mp3file = '"'+trackNumberCDDB+" - "+trackTitle+'.mp3"'
        cmd = 'lame --ta "%s" --tl "%s" --tn "%s" --tt "%s" --preset standard %s %s' % (artist,title,trackNumberCDDB,trackTitle,file,mp3file)
        print "Beginning conversion...%s\n" % file
        print "Artist: %s" % artist
        print "Album: %s" % title
        print "Track Number: %s" % trackNumberCDDB
        print "Track Title: %s\n" % trackTitle
        print 'Command: %s\n' % cmd
        syscall = os.system(cmd)
        if syscall != 0:
            raise RuntimeError, "lame returned non-zero exit status! %" % syscall

os.chdir("%s/%s/%s" % (startDir,artist,title))
os.system("rm *.wav")
EDIT: Fixed broken case where only one match found. Sorry