Title Tagger script unexpectedly repeating values - why?

I’m trying to tag live tracks with the recording disambiguation comment if it has one, e.g.

It has the title “I Need You” and I want it to be “I Need You (live, 2005-10-23: XM Performance Theater, Washington, DC, USA)”. in my file.

I’m using this tagger script:

$set(title,%title%$if(%_recordingcomment%, \(%_recordingcomment%\)))

But what I get is

I Need You (live, 2005-10-23: XM Performance Theater, Washington, DC, USA) (live, 2005-10-23: XM Performance Theater, Washington, DC, USA) (live, 2005-10-23: XM Performance Theater, Washington, DC, USA) (live, 2005-10-23: XM Performance Theater, Washington, DC, USA) (live, 2005-10-23: XM Performance Theater, Washington, DC, USA) [… repeated MANY more times]

A few things I noticed:

  • It only happens with tracks that have a file.
  • The title is normal in the treeview on the right, but not in in the tag list below or in a file naming script.
  • The “Move disambiguation to album title” script from Scripts — MusicBrainz Picard v2.9alpha1 documentation works fine.

I’ve tried restarting Picard, refreshing the album and removing all plugins, naming scripts and other tagging scripts to no avail.

I’m about to try a clean install with default settings.

What’s going on here?



This script has a flaw: if you add the _recordingcomment to the title it becomes part of the title. If you execute it again it adds the _recordingcomment to the already complete title. I suppose you executed it more than once. For the first time it should work.

1 Like

Because it’s a bit destructive to point out what’s wrong, not saying what will work, here my suggestion:

  $if($rsearch(%title%,%_recordingcomment%),,$set(title,%title% \(%_recordingcomment%\))))

Only IF there’s a _recordingcomment do anything, then IF the _recordingcomment is already part of the title, found/returned by rsearch(), do also nothing (after the first comma nothing), IF NOT (after the second comma), only then, SET the new value for title.
But it would fail, if the text was changed on MB, so it’s probably better to only search for the first characters:

  $if($rsearch(%title%,$substr(%_recordingcomment%,0,4)),,$set(title,%title% \(%_recordingcomment%\))))

Yes, I’m tweaking and testing naming and tagging scripts and refreshing after each change.

What was confusing me is it was adding 30 or more duplicates at the end, like something’s stuck in a loop. I can see it adding a duplicate on each refresh (or doubling each time), but even if I only set a tag once it was still blowing up.

I like your suggestion of putting processing in $if blocks, I find that much easier to follow and it feels more reliable than many nested $set(foo$if(bar),baz,wibble).

In any case, thank you!

1 Like

My pleasure!
But you should not use the second version. It’s probably not necessary or makes it worse.

  1. If you don’t keep “title” (Preserve these tags…), there should be no problem anyway. It will always be built anew with new data.
  2. But even if you keep “title”, it’s better for the script to fail in case of changes, because otherwise you will not notice and miss them completely.

I have to thank you for this idea!

I found out, I really like the idea of adding the recording disambiguation to the track titles, because it’s information otherwise not available at all. But (for me) it should be added in case of live recordings only, to avoid comments like “this is the short version without telephone ringing” being added to the track title. Therefore I made a little change:

  $if($rsearch(%title%,%_recordingcomment%),,$set(title,%title% \(%_recordingcomment%\))))

… if there is no _recordingcomment or it does not start with “live”, an empty string will be returned and nothing will be done.

EDIT: substr() removed from script

1 Like

That would miss comments like “Recorded live at…” so you might consider changing your $startswith() check to use $find() instead.

1 Like

Thanks, yes! But disambiguations like that should be corrected as they are not conform with the GL for live recordings :wink:

(And I thought about missing (by purpose) some with “partially recorded live…” from my collection which I like to treat as studio recordings)

In that case, perhaps a regular expression search something like /.*([Rr]ecorded )?[Ll]ive/

EDIT: Sorry, I was thinking of disambiguation rather than track comment. You’re right, that doesn’t match the guideline.

1 Like

No reason, your input is always welcome!
But in this case I chose startswith() to make sure that only real live recordings will have this comment added to the track title.

1 Like

Breaks on (version with Clive on bongos) ? (Sorry - I can break any algorithm… :rofl: :hammer: )

@ernstlx - Think I am going to borrow that script of yours. Fits my needs well. How would one add (demo, 1999-09-08: blah) ? How to tweak startswith live to startswith live or demo?

1 Like

Should work with $or($startswith(…),$startswith(…))
but I have not tested something. If one or the other condition matches, do it. $or() is always a bit tricky

Sounds good to me. As it would be impossible to start with both demo and live, OR seems perfect here.

I’ll see if I can find the example that uses (demo, like that and test it.


1 Like

But you have to consider that demo is often included in the track title anyway.
(and I have to consider that the same is true for “live” :wink:)

1 Like

That’s it. I’m done with trying to help people in this forum if all I get is smart ass responses.

I mean, really, what value does that comment add to the conversation?


Probably you have to deal with this kind of humor.
And you have helped me a lot!!! :slightly_smiling_face:

Really deeply sorry. I am used to testing software and often spot odd cases where something acts in an unexpected way. I was genuinely trying to help by showing a loop hole. The letters “live” are in that phrase

I am sorry that I am at fault here for my jokey response. It was not a criticism of your or your work. I have learnt a lot from you and really appreciate your input.

I am just really bad at communicating some days. Very sorry.


This is all a bit odd. Have you been executing this script manually on the file (via context menu “Scripts…”)?

Because if you have this as a tagger script that runs automatically when the release is loaded this should not happen. And I also can’t reproduce any behavior like that. It would apply the script to the data loaded from MB. But of course if you execute this script manually on the files which already have been manipulated the disambiguation would be added every time you run the script.

I suppose, that’s what has happened. :slight_smile:

@xhiris ← Also, I assume you want the script to run automatically. Otherwise you would have to make sure to run the script again every time you reload the files into Picard.
I tried to make the script usable for automatic execution on all releases:

    $set(title,$rreplace(%title%,\\s\\\(live.*\\\),) \(%_recordingcomment%\))

Compared to the above version I used $rsearch() which accepts “regular expressions” to extend the search string by either comma OR colon (that’s what [\,:] means). To avoid regular expressions you could look for both variants and connect them with $or():


The script should make changes only in cases with additional information in _recordingcomment, not if it’s only (live)
That’s necessary because I remove track title disambiguation if it starts with “live”, and I’m trying to make sure there’s more information in _recordingcomment than in the track title disambiguation which will be removed, e.g. “Title (live & unplugged version)” should not be replaced by “Title (live)”.

I remove the disambiguating comment from the title with $rreplace - regular expressions are unavoidable in this case - which cuts away something like " (live at …)" from the track title ← $rreplace(text,pattern,replace) where “replace” is empty. If “pattern” is not found in “text”, it remains unchanged.
This happens inside the $set() function and the return value from $rreplace() is extended with " (%_recordingcomment%)" and written to the title tag.

For @IvanDobsky I got an extended version including “demo”:

    $set(title,$rreplace($rreplace(%title%,\\s\\\(live.*\\\),),\\s\\\(demo.*\\\),) \(%_recordingcomment%\))

I’ve been getting some very strange results that I can’t reproduce consistently, or I’m missing something.

TL;DR I’ve been running most of these scripts automatically, but I’m not sure I understand when/how Picard updates the data. I expect it would only run when data gets loaded from MusicBrainz, and that only happens if you add stuff to the treeview on the right or hit “Refresh”.

In a few cases, when I’m running these scripts automatically, the duplicate (live …) stuff gets added not just when refreshing the album, but as I move from track to track in the treeview on the right. I’ve been trying to find steps to reproduce this consistently but I’m not having much luck.

Album title will be something like “Foo bar baz song (live at whatever stadium)” in the album node, and “Foo bar baz song (live at whatever stadium) (live at whatever stadium)” in the tracklist. If I click on another track then click back again (without refreshing or changing anything), it doubles up again “Foo bar baz song (live at whatever stadium) (live at whatever stadium) (live at whatever stadium) (live at whatever stadium)” and again each time I click a different track in the list. It doesn’t ever change the value in the “album” node, just the track.

Could this be a bug, or am I misunderstanding when the automatic scripts run? I’ve been messing with code in plugins, but I think I’ve reinstalled Picard after wiping out all my local files and settings and it’s happening on a fresh install.