Foobar2000 - Massive Masstagger Scripting (updated 07-29-05)

This tutorial deals exclusively with Foobar2000, its built-in Masstagger, and its use of formatting strings. If you are not familiar with any of that, this will come off sounding like some crazy moon-language. Also, since it is using your tags to redesign your folder structure, it assumes that you have tagged your files properly.

Sections:

Intro

The goal is to put the right files in the right place. There are many reasons why you should properly organize your files:

You could move them by hand, but you might go bonkers if you've got a few hundred albums to do. You could use some other database-driven application to manage everything for you, but its way of doing things is usually fixed to a single naming scheme (ex. - "artist/album/title"). And if it doesn't tell you outright, you'd have to manually see what it's doing. If you decide to move or rename files without the use of that application, you will confuse its database. Essentially, having something else do it for you puts you one-step removed from your data.

Foobar's Masstagger allows you to automate the process through the use of tag variables and script commands. With a sufficient renaming script, you can create and manage different naming schemes at the same time, and that is what this tutorial is all about.

(Foobar also has a database, so it could very easily replace other music managing software. But that's a different tutorial.)

But first you need to make sure your tags are in order. If you are unsure of this, please do it now. I recommend using the flipside of the Masstagger: Edit Tags. There's a wonderful tutorial over at Hydrogenaudio:

FB2K's Masstagger, an Unofficial Beginners Guide

In fact, it's better to rename based off your tags rather than the other way around. You cannot guess the tags from your filenames for your entire library at once unless all of your files and folders are structured the same. And as I will point out later, albums can come in many different shapes and sizes.
 

Design Philosophy I

Don't move any files yet, we are only designing a naming scheme.

Think about one music track:

(See? This is complicated already. Are you sure you've tagged all your files?)

It makes the best sense to go from the most general to the most specific. (I start with genres, most people don't. I'll get to that.) This is the basic idea: genres contain artists who make albums that contain tracks.

genre
|
+ artist
  |
  + album
    |
    + track

To put it in path format:

\genre\artist\album\track

This is very efficient because there is no redundant data in the file path, and it's very easy to drill-down if you know what you're looking for. There also won't be files anywhere except at the very end. This is by design.

If you leave it like this, everything will be listed in alphabetical order. At the track level (the end of the path), this is a problem:

Rock
|
+ The Beatles
  |
  + Abbey Road
    |
    + Because
    + Carry That Weight
    + Come Together
    ...

For those of you not familiar with Abbey Road, "Come Together" is track 1. Once the track number is part of the filename, the files will sort properly. For readability, I recommend a dash as a delimiter (with a space on both sides):

Rock
|
+ The Beatles
  |
  + Abbey Road
    |
    + 01 - Come Together
    + 02 - Something
    + 03 - Maxwell's Silver Hammer
    ...

When you move out to the album level, the problem rears its ugly head again:

Rock
|
+ The Beatles
  |
  + Abbey Road
  + Revolver
  + Rubber Soul

Of those albums, Rubber Soul was 1965, Revolver was 1966, and Abbey Road was 1969. To fix it, we'll do the same thing as we did with the tracks. This time, we'll apply the album dates to the album folder name:

Rock
|
+ The Beatles
  |
  + 1965 - Rubber Soul
  + 1966 - Revolver
  + 1969 - Abbey Road

At the next level though, the artist names stand alone. There's simply nothing to change (aside from getting more music):

Rock
|
+ Brian Eno
+ The Beatles
+ U2

A Little Note on Genres:

Most people wouldn't include them, but I'm weird. Some people create sub-genres, but I'm not that weird. I just feel uncomfortable doing things like putting Autechre (scatterbrained electronic) in the same place as Nickel Creek (bluegrass), so I end up creating my own subjective genre names:

Bluegrass
Ambient
Classical - New Age
Comedy - Speech
Dance
Electronic
Game
Rap - Urban
Rock
Soundtrack

Unfortunately, and this is why most people don't like genres, I have to make some judgment calls when dealing with experimental crossover artists. Like where the heck do you put Raymond Scott? His early work in the 30's and 40's was swing, and then from 1946 onward, he created electronic music. Brian Eno is equally confusing: sometime in the 70s, he went from proto-punk to ambient. But he still made a couple rock albums after he started making ambient albums. For these really schizophrenic ones, I might tag their albums as different genres, and that will give the artists multiple folders.

If I find something that doesn't directly fit under one of my genres, I'll make it fit! :)
 

To conclude this section, our basic naming scheme is:

\genre\artist\date - album\tracknumber - title

written as a string of TAGZ variables:

\%genre%\%artist%\%date% - %album%\%tracknumber% - %title%

I am not claiming this is the best scheme available, but it is the basis for the rest of the tutorial.
 

Design Philosophy II

This scheme covers most albums -- when an artist creates a bunch of tracks on its own, and puts them together.

(1) normal album
description : just your usual album by one artist.
tags : Genre, Artist, Album, Date, Tracknumber, Title
conditions : cannot have an Album Artist tag

naming scheme:
\%genre%\%artist%\%date% - %album%\%tracknumber% - %title%

examples:
\Electronic\The Orb\1995 - Orbus Terrarum\01 - Valley
\Rock\The Beatles\1969 - Abbey Road\01 - Come Together

 

That's fine and dandy, but what if an artist puts a bunch of its favorite songs together that it didn't write? We've got an album with multiple artists! If we use our original formatting string, it would be massively confusing to split this up by artist. Individual tracks would be scattered everywhere! (That other piece of software I mentioned does this. *shudder*) Since one artist compiled the album, and a different one wrote each track, we will use the %artist% tag to denote the track artist, but we'll create a tag for the album artist called %album artist%. Essentially, we have to denote that the album artist is not taking credit for the track, it still belongs to the original artist.

More info about the album artist tag: Foobar2000 Encouraged Tag Standards

Since the artist tag is likely to change from one track to the next, we will move it to the filename. Why put the tag in parenthesis, you ask? It's just a visual delimiter. Since some song titles have dashes in them, it may be difficult to see where the artist name ends and the track title begins (especially if you are importing tags with the Masstagger's "guess by filename" function).

(2) compilation by artist
description : each track was done by a different artist, and an artist compiled the album
tags : Album Artist, Artist, Album, Date, Tracknumber, Title
conditions : 'Album Artist' refers to compilation artist, Artist' refers to track artist

naming scheme:
\%genre%\%album artist%\%date% - %album%\%tracknumber% - (%artist%) - %title%

example:
\Electronic\The Orb\2003 - Back To Mine\01 - (Aphex Twin) - Polynomial-C

 

Now what if you've got one of those compilation albums where there's just a bunch of songs by different artists, but no one is taking credit for putting it together? We'll still use the artist tag for the track artist, but the album artist tag takes on a new role. It contains "VA" which means "various artists". It also prefixes "date - album" to group all the "VA" albums together in the folder structure, otherwise it wouldn't make sense scattered among all the artists in the folder tree. (EDIT: This is subject to change. I'm starting to think it's ugly.)

(3) compilation disc (various artists)
description : each track was done by a different artist, but there's no artist for the entire album
tags : Genre, Album Artist, Artist, Album, Date, Tracknumber, Title
conditions : 'Album Artist' must equal "VA", 'Artist' refers to track artist

naming scheme:
\%genre%\%album artist% - %date% - %album%\%tracknumber% - (%artist%) - %title%

example:
\Rap - Urban\VA - 1998 - Pure Funk\01 - (The Commodores) - Brick House

 

What about Soundtracks?

The first thing that comes to mind with a soundtrack is the name of the movie (or play, or whatever) that it's associated with, and this is most often the name of the album. Since the title is more important than the date, these can be listed a bit differently from the other schemes. In terms of formatting, most soundtracks are essentially compilation discs. One major difference is that they get their own genre folder -- "Soundtrack". And as I mentioned before, you're likely to be more concerned with the name of the album, so it goes before the date.

(4) soundtrack by various artists
description : like a compilation disc, but it's a collection of music from a different work
tags : Genre, Album Artist, Artist, Album, Date, Tracknumber, Title
conditions : 'Genre' must equal "Soundtrack", Album Artist' must equal "VA", 'Artist' refers to track artist

naming scheme:
\%genre%\%album% - %date%\%tracknumber% - (%artist%) - %title%

example:
\Soundtrack\Trainspotting - 1996\01 - (Iggy Pop) - Lust For Life

 

If one artist writes the entire score, we should add the artist name somewhere in the folder structure. To keep all soundtracks sorted similarly, the %artist% tag will go in the folder name after the date.

(5) soundtrack by single artist
description : like a normal album, but not intended to be part of the artist's discography
tags : Genre, Artist, Album, Date, Tracknumber, Title
conditions
: 'Genre' must equal "Soundtrack"

naming scheme:
\%genre%\%album% - %date% - %artist%\%tracknumber% - %title%

example:
\Soundtrack\Amélie - 2001 - Yann Tiersen\01 - J'y suis jamais allé

 

version 0.9 enhancements:

What if you have one track, but you don't have the rest of the album? You know the name of the song, you know who did it, and you know which genre it belongs to, but other than that, it's just a file floating around all by itself.

(6) loose file
description : loose file
tags : Genre, Artist, Title
conditions
: cannot have Album, Date, Tracknumber tags

naming scheme:
\%genre%\%artist% - %title%

example:
\Rock\Van Halen - Poundcake

(7) loose soundtrack file
description : loose file from a soundtrack
tags : Genre, Artist, Title
conditions
: Genre must equal "Soundtrack", cannot have Album, Date, Tracknumber tags

naming scheme:
\%genre%\%artist% - %title%

example:
\Soundtrack\Harold Faltermeyer - Axel F

 

Scriptwriting (intro)

Before proceeding: make sure your files are properly tagged or this script will severely butcher your filenames. I will not be held responsible if you nuke your own files.

Now it's time to create a single script that will generate all five of those different naming schemes. The required tags for this script are:

The Masstagger's scripting functions allow for conditional formatting. Look over the title formatting help file and you'll see what I mean:

a mirror of Foobar's Title Formatting Help

Depending on your programming experience, this may look intimidating, or it may look like child's play. Whatever the case, Foobar has its own little way of doing things. For example, version 0.8 has this:

LIMITATION: The Masstagger uses slashes as end-of-line characters, so you cannot use folder delimiters in any statement.

For version 0.8, we will have to work one folder at a time. This bloats the code something fierce, but it works. So, instead of trying to create the complete set of paths all at once, we will work our way from left to right, generating everything from one slash to the next, one level of folders at a time.

Fortunately, version 0.9 does not have this limitation! Unfortunately, you cannot use the version 0.8 script with Foobar 0.9 because it processes variables differently.

More about the titleformatting upgrades in version 0.9:

Titleformat Introduction

Titleformat Reference

Depending on the Foobar version you use, you will have to select a compatible version of the script:

script version 0.8

script version 0.9

Even if you are using version 0.8, I recommend installing Foobar 0.9 and trying its script. (Please install it to a different folder!!) You may be surprised at how much smaller the code will be. Even after I added support for two more naming schemes (single tracks), and a %disc% variable, the script is considerably much smaller than the 0.8 version.

The most important part: I have stopped all development on the v0.8 script. All future enhancements will go toward version 0.9.

 

Creating the script for Foobar v0.8

The first folder in the path of all our naming schemes is Genre. So, start with "%genre%\"

(as we design it, the script will be prefixed with a vertical orange line)

%genre%\

Up to this point, the parts of the schemes that the script can generate will be highlighted below:

scheme output format
1 \%genre%\%artist%\%date% - %album%\%tracknumber% - %title%
2 \%genre%\%album artist%\%date% - %album%\%tracknumber% - (%artist%) - %title%
3 \%genre%\%album artist% - %date% - %album%\%tracknumber% - (%artist%) - %title%
4 \%genre%\%album% - %date%\%tracknumber% - (%artist%) - %title%
5 \%genre%\%album% - %date% - %artist%\%tracknumber% - %title%

That was easy, but it gets pretty dense from here on, so be careful.

Each one of our naming schemes needs different data at the next folder level, and these differences are due to different conditions:

scheme format for this folder level condition
1 %artist% %album artist% doesn't exist
2 %album artist% %album artist% is not "VA"
3 %album artist% - %date% - %album% %album artist% is "VA"
4 %album% - %date% %album artist% is "VA"
and %genre% is "Soundtrack"
5 %album% - %date% - %artist% %album artist% doesn't exist
and %genre% is "Soundtrack"

So in order to make one huge string that will generate the formats for all the schemes, we need to tell Foobar about the conditions. And we can do that by nesting $if commands with $stricmp (string compare) statements.

According to the Title Formatting Help (above), the if statement is written as:

syntax:
$if(position1,position2,position3)

definition:
If position1 returns positive, then display/execute position2, otherwise display/execute position3.

Also, the string compare statement is:

syntax:
$stricmp(position1,position2)

definition:
Compares position1 and position2, doesn't work unless it's in position1 of an if statement.

To kick it off, position1 of the first if statement can be written as:

$if(%album artist%,

With this, we can output under two conditions:

Since schemes 1 and 5 depend on %album artist% not existing, we can place them together in position3. We have to split them apart by testing them for "Soundtrack". (new parts in bold)

$if(%album artist%, ... ,$if(stricmp(Soundtrack,%genre%),%album% - %date% - %artist%,%artist%))/

This leaves position2 for us to output on these conditions:

Test whether or not VA exists in %album artist%

$if(%album artist%,$if($stricmp(VA,%album artist%), ... , ...),$if(stricmp(Soundtrack,%genre%),%album% - %date% - %artist%,%artist%))/

Add the genre test in position2 which will create schemes 4 and 3

$if(%album artist%,$if($stricmp(VA,%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date%,%album artist% - %date% - %album%), ...),$if(stricmp(Soundtrack,%genre%),%album% - %date% - %artist%,%artist%))/

Since the VA test is in position2 of the %album artist% test, position3 of the VA test would imply "album artist exists, but isn't VA, and isn't a Soundtrack", this will generate scheme 2

$if(%album artist%,$if($stricmp(VA,%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date%,%album artist% - %date% - %album%),%album artist%),$if(stricmp(Soundtrack,%genre%),%album% - %date% - %artist%,%artist%))/

Combine everything up to this point, and we have:

%genre%\$if(%album artist%,$if($stricmp(VA,%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date%,%album artist% - %date% - %album%),%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date% - %artist%,%artist%))\

scheme output format
1 \%genre%\%artist%\%date% - %album%\%tracknumber% - %title%
2 \%genre%\%album artist%\%date% - %album%\%tracknumber% - (%artist%) - %title%
3 \%genre%\%album artist% - %date% - %album%\%tracknumber% - (%artist%) - %title%
4 \%genre%\%album% - %date%\%tracknumber% - (%artist%) - %title%
5 \%genre%\%album% - %date% - %artist%\%tracknumber% - %title%

The next folder level is tricky. See how the first two schemes need another folder level after this one, but the bottom three schemes finish here? We could generate all of them right now, but this is too convenient to pass up: notice the filename format (rightmost) for all the schemes with %album artist% (schemes 2, 3, 4) -- they're all the same! The same goes for those without %album artist%, they group up as well. If you think about it, we have just written the pseudocode for generating the filename level for all schemes right here in this paragraph!

Basically:
if(%album artist% exists, then "%tracknumber% - (%artist%) - %title%", else "%tracknumber% - %title%")

NOTE: Foobar's formatting commands use parenthesis as special characters. If you want to output them, you have to surround them with single quotes.

example:
(%artist%) will return an error because Foobar is expecting a command
'('%artist%')' will return the value of %artist% within parenthesis (exactly what we're looking for)

NOTE: When using ID3v2 or APEv2 tags, the %tracknumber% field is not limited to two numerical digits. It can contain practically anything. To prevent your filenames from looking like "03 of 11 - The Name of The Song", do not use a bare %tracknumber% field. To clean this up, Foobar offers the $num command:

syntax:
$num(integer,digits)

definition:
Keeps the number "integer" at the number of digits specified in "digits". If "integer" is longer than "digits", it is concatenated. If it is shorter, it is padded with zeroes.

example:
$num(%tracknumber%,2)
If %tracknumber% is "3", then $num will return "03"
If %tracknumber% is "03/11" or "03 of 11", then $num will return "03"

That means the final level of the string is:

... $if(%album artist%,$num(%tracknumber%,2) - '('%artist%')' - %title%,$num(%tracknumber%,2) - %title%)

If we piece together what we've created up to now, we get this (mind the gap: "...")

%genre%\$if(%album artist%,$if($stricmp(VA,%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date%,%album artist% - %date% - %album%),%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date% - %artist%,%artist%))\ ... $if(%album artist%,$num(%tracknumber%,2) - '('%artist%')' - %title%,$num(%tracknumber%,2) - %title%)

And we realize that we aren't lacking much:

scheme output format
1 \%genre%\%artist%\%date% - %album%\%tracknumber% - %title%
2 \%genre%\%album artist%\%date% - %album%\%tracknumber% - (%artist%) - %title%
3 \%genre%\%album artist% - %date% - %album%\%tracknumber% - (%artist%) - %title%
4 \%genre%\%album% - %date%\%tracknumber% - (%artist%) - %title%
5 \%genre%\%album% - %date% - %artist%\%tracknumber% - %title%

Even though we're just missing "%date% - %album%\", we can't just slap it in there because it would apply to all the schemes.

scheme output format condition
1 %date% - %album% %album artist% doesn't exist
2 %date% - %album% %album artist% is not "VA"
3 <no output> %album artist% is "VA"
4 <no output> %album artist% is "VA" and if %genre% is "Soundtrack"
5 <no output> %album artist% doesn't exist and if %genre% is "Soundtrack"

We have to check for all conditions, but simply not generate anything for those schemes that are already complete. So, we'll do the usual and check for %album artist%, and test it for "VA" in position2:

 $if(%album artist%,$if($stricmp(VA,%album artist%),

The next position (position2 of the VA statement) will generate output when %album artist% is "VA". Notice that's the third scheme, and we don't want to display anything for that scheme right now. So we'll leave it empty (by adding a comma).

 $if(%album artist%,$if($stricmp(VA,%album artist%),,

After that is where we output when %album artist% is not "VA". This is where scheme 2 gets created:

 $if(%album artist%,$if($stricmp(VA,%album artist%),,%date% - %album%),

Now we're in the position that outputs when %album artist% doesn't exist. Both schemes 1 and 5 need that, but we don't want to print 5. The only thing separating it from scheme 1 is that 5 is generated when the "Soundtrack" test is passed -- so position2 of that $if statement will remain blank as well.

$if(%album artist%,$if($stricmp(VA,%album artist%),,%date% - %album%),$if($stricmp(Soundtrack,%genre%),,

This last position outputs when both %genre% is not "Soundtrack" and %album artist% doesn't exist -- that's scheme 1.

$if(%album artist%,$if($stricmp(VA,%album artist%),,%date% - %album%),$if($stricmp(Soundtrack,%genre%),,%date% - %album%))\

 

Now it's time to combine everything into one big, massive script!

%genre%\$if(%album artist%,$if($stricmp(VA,%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date%,%album artist% - %date% - %album%),%album artist%),$if($stricmp(Soundtrack,%genre%),%album% - %date% - %artist%,%artist%))\$if(%album artist%,$if($stricmp(VA,%album artist%),,%date% - %album%),$if($stricmp(Soundtrack,%genre%),,%date% - %album%))\$if(%album artist%,$num(%tracknumber%,2) - '('%artist%')' - %title%,$num(%tracknumber%,2) - %title%)

Beauty, eh?

Skip to Usage if you do not have Foobar version 0.9.

 

Creating the script for Foobar v0.9

Since v0.9 can take slashes (folder delimiters) inside $if() statements, we can generate the entire path at once. The big upgrade however is that the %% fields no longer directly reference their tag counterparts.

For instance, %album artist% is now defined as:

$if3($meta(album artist),$meta(artist),$meta(composer),$meta(performer))

That means if the album artist tag does not exist, it will return the artist tag. If that doesn't exist, it will try composer, and so on. Logically, this makes sense. If the album artist tag does not exist, that means the artist tag is now representing the artist for that entire album -- the "album artist". (As for the other two, I have no idea when they would be used because there is no reason why a track would not contain an artist tag.)

When the album artist tag is present, we will also need to return the artist tag, but what is the artist tag representing in this case? The "track artist". Thankfully, they have created the %track artist% field, and defined it thusly:

$meta(artist), if $meta(album artist) is different than $meta(artist), otherwise this field is empty.

Basically, they have slipstreamed the old Encouraged Tag Standards into the new remapped titleformats. Due to these new definitions, we are no longer required to nest $if() statements looking for the existence of certain tags, the new definitions take care of it for us.

With that knowledge, all of the schemes can be written as:

1 %album artist%\%date% - %album%\%tracknumber% - %title%
2 %album artist%\%date% - %album%\%tracknumber% - (%track artist%) - %title%
3 %album artist% - %date% - %album%\%tracknumber% - (%track artist%) - %title%
4 Soundtrack\%album% - %date%\%tracknumber% - (%track artist%) - %title%
5 Soundtrack\%album% - %date% - %album artist%\%tracknumber% - %title%
6 %album artist% - %title%
7 Soundtrack\%album artist% - %title%

Notice how they overlap when they're all grouped up like that? I mean, aside from the genre-specific folders, the first four are %album artist% (not in #4), %date%, %album%, %tracknumber% "(%track aritst%)" (not in #1), and %title%; with the occasional "\" or "-" in the way. Number 5 is different only because it moves %album artist% to the end of the first folder name, and #6 and #7 are basically #1 and #5 without all the stuff in the middle.

We'll kick it off with %genre%:

%genre%\

Now let's take care of the "Soundtrack"-check:

%genre%\$if($strcmp(Soundtrack,%genre%), ... , ... )

Position2 of this statement should contain the items to be returned if the genre is "Soundtrack", and position3 should contain those items for when the genre is anything else. At first, we would be inclined to copy the rest of each of the schemes into each of their respective positions in the $if() statement, but look at all the redundant information:

Position 2:

scheme 4 -- %album% - %date%\%tracknumber% - (%track artist%) - %title%

scheme 5 -- %album% - %date% - %album artist%\%tracknumber% - %title%

Position 3:

scheme 1 -- %album artist%\%date% - %album%\%tracknumber% - %title%

scheme 2 -- %album artist%\%date% - %album%\%tracknumber% - (%track artist%) - %title%

scheme 3 -- %album artist% - %date% - %album%\%tracknumber% - (%track artist%) - %title%

First off, the first two folder levels of #1 and #2 are are identical, so that part of position 3 can be written as:

%album artist%\%date% - %album%\

Scheme 3 changes things because it uses a dash between %album artist% and %date% instead of a slash. When does it need either one? The dash comes when %album artist% is "VA", otherwise it returns a slash. With an %if() statement crammed in there, this position becomes:

%album artist%$if($strcmp(VA,%album artist%), - ,\)%date% - %album%\

But what about the final part (the filename itself)? It has a "(%track artist%)" stuck in there! Remember the new definition of the %track artist% field? It will only return the artist tag if it is different from the album artist tag, otherwise it will not return anything. But if we include it as-is, #1 will return nothing but two dashes and the two parenthesis, and that's not what we want.

NOTE: Foobar's formatting commands use parenthesis as special characters. If you want to output them, you have to surround them with single quotes.

example:
(%artist%) will return an error because Foobar is expecting a command
'('%artist%')' will return the value of %artist% within parenthesis (exactly what we're looking for)

Here's a clever invention (one that for some reason I decided not to use in the v0.8 script): square brackets!

Anything that is between square brackets will only be returned if the tag that is also within the brackets returns something.

For encapsulating extra characters (dashes, slashes, spaces) inside brackets, pay attention to how the neighboring tags are 'connected' to each other, and which of those tags might be optional. In the case of the track artist, it will return nothing if the artist and album artist fields are the same (that is, the track doesn't really have an album artist tag).

When it is present, it requires a dash on both sides of it. When it is not present, there's only one dash between %tracknumber% and %title%. If we just bracket the %track artist% field, both dashes will still appear when track artist isn't there. But if you bracket both of the dashes, they'll both disappear when the track artist does.

When %track artist% returns negative:

  • input
    • %tracknumber% - ['('%track artist%')'] - %title%
  • output
    • tracknumber - - title

 

  • input
    • %tracknumber%[ - '('%track artist%')' - ]%title%
  • output
    • tracknumbertitle

It works when we grab only one of the dashes:

\%tracknumber% - ['('%track artist%')' - ]%title%

I could have bracketed the left dash instead of the one on the right, but I am thinking ahead. What if the track doesn't have a tracknumber? (It's an odd scenario, but see 'possible alternative' below). If the tracknumber is optional, and you don't bracket the dash to immediately its right, you'll end up with "\- title", which is pretty ugly.

Since the final folders of #4 and #5 (position 2 of the $if() statement) are identical to those of #1 and #2 (position 3), they can be represented with that exact statement we just made, which can therefore be moved outside the $if() statement.

Rewritten:

%genre%\$if($strcmp(Soundtrack,%genre%), ... , ... )\%tracknumber%[ - '('%track artist%')'] - %title%

Let's go ahead and stick the newly trimmed-down position3 in there:

%genre%\$if($strcmp(Soundtrack,%genre%), ... ,%album artist%$if($strcmp(VA,%album artist%), - ,\)%date% - %album%)\%tracknumber% - ['('%track artist%')' - ]%title%

As for position2, it's basically "%album% - %date%" with " - %album artist%" tacked on if it equals anything but "VA" (return nothing if it does). Yep, that's really easy:

%album% - %date%$if($strcmp(VA,%album artist%),, - %album artist%)

when added:

%genre%\$if($strcmp(Soundtrack,%genre%),%album% - %date%$if($strcmp(VA,%album artist%),, - %album artist%),%album artist%$if($strcmp(VA,%album artist%), - ,\)%date% - %album%)\%tracknumber% - ['('%track artist%')' - ]%title%

Let's sit back and take a break, and realize that this string will generate all five of the original schemes exactly the same as the version 0.8 string. This one is 224 characters, while the v0.8 is 455 characters! The new changes eliminated a LOT of redundancy!

But one part where I'm having trouble eliminating redundancy is when I make it generate single tracks (the new schemes, #6 and #7).

The easy way is to surround everything after the %genre% field with an album-test

%genre%\$if(%album%,$if($strcmp(Soundtrack,%genre%),%album% - %date%$if($strcmp(VA,%album artist%),, - %album artist%),%album artist%$if($strcmp(VA,%album artist%), - ,\)%date% - %album%)\%tracknumber% - ['('%track artist%')' - ]%title%,%artist% - %title%)

This uses the assumption that single tracks will not have an album tag. If they do, and they're the only tracks you have from their respective albums, I recommend removing those tags or you will have album folders containing only one track. (You'll then be tempted to think that since you have a folder for a given album, you must have all of its tracks.)

But notice how I put "%artist% - %title%" on the end.. It works, but it's disconcerting because those fields are already being generated within the soundtrack-test. Don't worry, since they're safely nestled within another $if() statement, they won't be generated twice, but it isn't the most elegant solution because two %if() statements are generating the same fields.

Possible alternative?

In order for the single tracks to return the %album artist% and %title% tags from within the soundtrack-test, you would have block out the stuff you don't want returned (not only the tags, but the connecting dashes and slashes) by surrounding it with square brackets. Since single tracks don't use %album%, %date%, or %tracknumber%, they can be blocked (remember to block them in such a way that their neighboring dashes & slashes won't show up where you don't want them to):

%genre%\$if($strcmp(Soundtrack,%genre%),[%album%][ - %date%]$if($strcmp(VA,%album artist%),, - %album artist%),%album artist%$if($strcmp(VA,%album artist%), - ,\)[%date% - ][%album%])[\%tracknumber% - ]['('%track artist%')' - ]%title%

The problem areas are highlighted in red. If this script were run as-is, the single tracks would have these problems:

#5 (extra slash)
%album artist%\- %title%

#6 (extra dash)
Soundtrack\- %album artist% - %title%

I can't use the existing %album artist% and %title% fields for single tracks without severely reworking the structure of these $if() statements, and possibly adding a couple more $ifs just to add a single character! Since these statements work for all five other schemes, I have decided to keep the album-test I created before and just live with a couple redundant fields. (If anyone can find a better solution than this, please let me know!)

Other additions:

%disc% support -- Some people use the %disc% tag to refer to multi-disc albums. It stores a single integer, is prefixed with "disc ", is surrounded by parenthesis, and the entire mess immediately follows the %album% field (delimited by a dash). Since it's optional, we have to surround it (including the dash) with square brackets. Also, the parenthesis have to be surrounded by single quotes or the $if() statement will get confused. After everything, it looks like this:

[ - '('disc %disc%')']

Added to the string:

%genre%\$if(%album%,$if($strcmp(Soundtrack,%genre%),%album%[ - '('disc %disc%')'] - %date%$if($strcmp(VA,%album artist%),, - %album artist%),%album artist%$if($strcmp(VA,%album artist%), - ,\)%date% - %album%[ - '('disc %disc%')'])\%tracknumber% - ['('%track artist%')' - ]%title%,%artist% - %title%)

optional fields -- Some people don't use a genre folder, so it, along with its corresponding slash should be contained in brackets. You could even go more extreme by bracketing every output field. Even if you didn't have the proper tags, the paths could be generated without extra characters floating around.

By the time everything is said and done, it comes out like this:

[%genre%\]$if(%album%,$if($strcmp(Soundtrack,%genre%),[%album%][ - '('disc %disc%')'][ - %date%][$if($strcmp(VA,%album artist%),, - %album artist%)],%album artist%$if($strcmp(VA,%album artist%), - ,\)[%date% - ][%album%][ - '('disc %disc%')'])\[%tracknumber% - ]['('%track artist%')' - ]%title%,[%artist% - ]%title%)

Even after all the additions, 316 characters is still smaller than v0.8!

 

Usage

Now that we've created a monster, what do we do with it?

Open a Foobar playlist, select all the files you want to organize, right click, and go to "masstagger / move, rename or copy files"
(this may not be the case if you have edited Foobar's menus. But if you have, then you probably know where you hid the Masstagger.)

Click the "edit" button next to "output filename format"

In this new window, click the "add button".

In *this* new window, make up a descriptive name under "display name", and paste the huge formatting string in "format".

Press "OK"

press "OK" again

select the "output file name format" you just created

..and take a look at the "Preview" area. Is anything butchered? If so, either tweak your code or press cancel and go to back to bed.

If everything looks good,

set "Do what" to "rename or move files"

If this is the first time you have tried this, I recommend setting it to "copy files".

uncheck "same as source file directory"

Set output directory to your root music folder.

For example, if you want normal albums to look like:
c:\music\genre\artist\date - album\num - title
..set it to "c:\music".

If this is the first time you have tried this, I recommend creating a temp folder to test the script first.

Select "create subdirectories according to \ and / characters"

now press "Run" and see what happens!