Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I've been trying out a few different music players recently and noticed that some (a lot) of my music would be missing from the library. It turns out that at some point, a plethora of my music files lost their .mp3/.ogg/.flac file extensions. I'm honestly not sure how this happened, but I'm confident it was something I did mistakenly (or maybe I thought it wouldn't matter since file extensions are mostly cosmetic anyway).

So I need to get these file extensions back. I've looked into pyrenamer, but I can't figure out how to match it to files without an extension and then tell it to add the correct file extension depending on the actual type of the file.

I've also looked at EasyTag. However, it also recognizes music files based entirely on their file extensions. So the music I want to fix doesn't even show up. Brilliant.

Any thoughts on how to do this? I certainly don't mind some command line, I'm just not sure which tools would be best and I also suck at regex.

share|improve this question
add comment

2 Answers 2

up vote 6 down vote accepted

Here's a bash script that renames the files passed to it based on their guessed format. It calls file to figure out the format by looking at characteristic patterns in the first few bytes. file -i prints lines like /path/to/file: type/subtype where type/subtype is a MIME type. The script then associates extensions to known types and renames the file to have the extension. Files that already have the extension are left alone. Files that have an unrecognized type are left alone. The script will prompt before overwriting a target file.

#!/bin/bash
# usage:
# fixmime ./{**/,}*
file --mime-type "$@" |
while read -r line; do
  file=${line%:*}
  type=${line##* }
  case $type in

    #Audio
    audio/x-flac) ext=flac;;
    audio/mpeg) ext=mp3;;
    application/ogg) ext=ogg;;

    #Video
    video/mp4) ext=mp4;;
    video/x-flv) ext=flv;;
    application/octet-stream) ext=webm;;
    application/x-shockwave-flash) ext=swf;;

    #Images
    image/png) ext=png;;
    image/jpeg) ext=jpg;;
    image/gif) ext=gif;;
    image/x-ico) ext=ico;;

    #Text
    text/plain) ext=md;; #markup your notes, even when they are plain
    text/html) ext=html;;
    text/x-pascal) ext=py;;
    text/x-c++) ext=js;; #conflicts with .cpp, so use prefered
    text/x-c) ext=scss;; #usualy it is .c
    text/x-shellscript) ext=sh;;
    application/pdf) ext=pdf;;

    #Fonts
    application/x-font-ttf) ext=ttf;;
    application/vnd.ms-opentype) ext=otf;;

    #Archive
    application/x-gzip) ext=tar.gz;;
    application/x-bzip2) ext=tar.bz;;

    *) continue;;
  esac
  [[ $file = *.$ext ]] || mv -i -- "$file" "$file.$ext"
done

Save the script as ~/bin/rename-based-on-content-type (or whatever you like) and make it executable (chmod +x ~/bin/rename-based-on-content-type). Pass the names of the files you want to rename to the script on the command line. If you have a directory tree /path/to/music/directory that you want to traverse recursively, invoke the script as

~/bin/rename-based-on-content-type /path/to/music/directory/{**/,}*
share|improve this answer
    
That worked brilliantly. As far as I can tell anyway. I also learned a bit more about bash scripting :) Thanks! –  greggory.hz Oct 14 '10 at 23:54
    
for some reason this didn't work on all the song, but I was able to quickly pick up the (very) few that it didn't catch using lltag –  greggory.hz Oct 15 '10 at 0:21
add comment

This bash script could do the trick:

#! /bin/bash

find ~/Music -type f | (while read path; do
    case `file -i "$path"` in
        *audio/mp3*|*audio/mpeg*) ext='.mp3' ;;
        *application/ogg*) ext='.ogg' ;;
        *flac*) ext='.flac' ;;
        *) continue;; # ignore unknown files
    esac

    newname="$(dirname "$path")/$(basename "$path" "$ext").$ext"
    if [ "$path" != "$newname" ]; then
        mv -v "$path" "$newname"
    fi
done)

The script uses file -i to read the MIME type of a file; I have no FLAC files here, so you might want to check what the MIME type for FLAC is by running file -i a_file.flac (and possibly adjusting the script source).

You can add an option -i to mv if you want to be asked confirmation before any file rename.

It might be a good idea to replace mv -v by echo mv -v and doing a test run before trying the actual renames -- the echo mv will print out the mv commands that would be executed by the script.

share|improve this answer
    
A lot of my mp3 files I ran file -i on return audio/mpeg instead of audio/mp3, maybe you could add that to your script? –  Alvin Row Oct 14 '10 at 23:37
    
@DoR, just add audio/mpeg) ext='.mp3' ;; in the first case section –  greggory.hz Oct 14 '10 at 23:46
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.