Greg's Tech blog

Sorting Music Files with Powershell

Wednesday 11 of January, 2012

I'd collected a bunch of music files overtime all in a single directory. I want to sort them into a folder structure arranged at the top level by artist and them by album.

I found a great article by Tobias Weltner here (cache) which is the basis for my script.

The details for music files can be accessed through a Windows Shell object and we can set that up like this:

$path = 'C:\Users\Public\Music\Sample Music\Maid with the Flaxen Hair.mp3'
$shell = New-Object -COMObject Shell.Application
$folder = Split-Path $path
$file = Split-Path $path -Leaf
$shellfolder = $shell.Namespace($folder)
$shellfile = $shellfolder.ParseName($file)

and once we have that we can list the possible attributes with this code

0..287 | Foreach-Object { '{0} = {1}' -f $_, $shellfolder.GetDetailsOf($null, $_) }

Now that you see how to read these Extended attributes, read Tobias' code for the Add-FileDetails function. It enumerates the requested attributes for a given file. I'll not repeat that code here.

What I needed was some code that would

  • enumerate all the files in a directory,
  • find the Artist and album name for each file
  • construct a destination path for each file
  • create any needed folders
  • move the files

Warning - This code is NOT pretty

$sourcepath = ""
   #enumerate fields & gather attributes
dir "$sourcepath*.*" |Add-FileDetails|foreach {
    $mfile = $_
       #build artist level path
    $mpath = "" + $mfile.Ext_Artists
    $mpath = "\Music\" + $mpath

      #build album level path and combine them
    $mAlbum = $mfile.Ext_Album
    $mapath = $mpath + "\" + $mAlbum
    write-host $mapath $mfile.name

    if (! (Test-path $mpath)) {
        echo "Creating artist folder: $mpath"
        mkdir $mpath
    if (!(test-path $mapath)) {
        echo "Creating album path $mapath"
        mkdir $mapath

       #assuming the path was created or already existed, move files
    if (Test-path $mapath) {
        Move-item -literalpath $mfile $mapath
    } else {
    echo "Unable to create path: $mpath"

(Note: I made one mod to Tobias' code that you may notice. Instead of the attributes prefixed with Extended_, I shortened it to Ext_)

One thing I had to deal with were special characters in some of the artist names and albums names. I did that be a series of -replace commands that i left out of the code above for readability. Here's a snippet. You may need to recreate this based on your data.

#replaces \, /, :, ;, and ' in names with an appropriate alternative
    $mpath = "" + $mfile.Ext_Artists
    $mpath = $mpath -replace "\\","-"
    $mpath = $mpath -replace("\/","-")
    $mpath = $mpath -replace(":","-")
    $mpath = $mpath -replace(";","-")
    $mpath = $mpath -replace("'","")