Replace characters once for whole filename?

All about user-defined episode / movie / file name format expressions
Post Reply
topbanana
Posts: 34
Joined: 22 Jan 2015, 04:51

Replace characters once for whole filename?

Post by topbanana »

Can we replace all the illegal characters just once for the whole resulting filename?
Instead of multiple times, once for the Name, again for the Title, again for the PrimaryTitle, yet again for the Localised Title, etc. etc?
As it can make the Episode/Movie Format veeeeeeeeery long and not as simple to build, read, follow.
Can we just surround a simple straight format with one Replace function and it's character replacements?

And yes, backslashes would need to be worked around for defining folders, if used (I'm not).

For example. Here's my Format for foreign TV shows, that includes the name & titles in the original language.

Format: Select all

{n.replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')} ({primaryTitle.replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')}) - {s00e00} - {t.replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')} ({localize[language].t.replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')}){' ('+vf.match(/720[pP]|1080[pP]|2160[pP]/)+') '}{af==8?' (7.1)':af==7?' (6.1)':af==6?' (5.1)':null} ({airdate.format('yyyy')}){'.'+lang.ISO2}
Having to define the replacements 4 times seems a bit cumbersome, seeing as it's just one filename that need to be made 'legal'.
User avatar
rednoah
The Source
Posts: 23002
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Replace characters once for whole filename?

Post by rednoah »

I see. You're replacing characters with similar-unicode characters. So the built-in validation dialog does not work for you... as it only allows you to strip illegal characters and and does not support user-defined custom replacement characters:
Screenshot



I think that copy & paste is a good and easy solution if you're new to code, but I also agree that code reuse is highly desirable in this case. The solution is to write the entire format in a single {...} expression so that you can build the entire file path in code, and apply custom character replacement at the end before returning the result. This will come at the cost of knowing how to read and write simple Groovy code at a somewhat higher level though.


I might rewrite your format like so to make it easier to maintain and easier to read:

Format: Select all

{
	allOf{
		// add original series name in parentheses (if different)
		def translation = primaryTitle
		n == translation ? n : n + ' (' + translation + ')'
	}{
		s00e00
	}{
		// add original episode title in parentheses (if different)
		def translation = localize[language].t
		t == translation ? t : t + ' (' + translation + ')'
	}
	.join(' - ')
	// replace illegal characters with similar-looking unicode characters
	.replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')
}
{
	// add 720p or above marker to high resolution content (i.e. never add 640p marker)
	height <= 640 ? null : ' (' + vf + ')'
}
{
	// add channel marker; OP does not use {channels} for some reason
	af == 8 ? ' (7.1)' : af == 7 ? ' (6.1)' : af == 6 ? ' (5.1)' : null
}
{
	// add episode airdate year
	' (' + airdate.year + ')'
}
{
	// add subtitle language tag
	'.' + lang.ISO2
}
:idea: Please read the FAQ and How to Request Help.
topbanana
Posts: 34
Joined: 22 Jan 2015, 04:51

Re: Replace characters once for whole filename?

Post by topbanana »

So 'allOf' is what we need.
For me, translating this back to a simple episode format, it'd be:

Format: Select all

{allOf{n}{s00e00}{t}.join(' - ').replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')} ({airdate.format('yyyy')})
It doesn't work without the 'join()' bit. Correct?

Could you add/document this to your Format Expressions page? https://www.filebot.net/naming.html. I've been wondering about this for literally years and didn't know it existed, and it's not easy to search for, not knowing what the correct search terms to use. So if a simple example of it is included on your Format Expressions page, we'd at least know what to search for, for the more detailed explanations and examples in the forums. And i'm sure that most users that are replacing illegal characters with look-alikes don't know about this, and are repeating the .replace multiple times, like i did (Which i saw and learnt from the huge number of examples in the forums).

I've changed my existing formats to have each bit on different lines, which absolutely does make it easier to read! Thanks!
User avatar
rednoah
The Source
Posts: 23002
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Replace characters once for whole filename?

Post by rednoah »

:arrow: Learn how {expressions} work and useful Helper Functions is a good place to get started.


The simple version will look more like this:

Format: Select all

{
	(n + ' - '  + s00e00 + ' - ' + t).replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')
}
replace() is a String method, so it'll work on all String objects. n gives you a String object, but you can make a new String object by combining other String objects and then use replace() on the result. If you have some coding expertise, it'll make sense naturally. If you don't have coding expertise then copy & paste is a good-enough solution. Asking the community for a better solution is also a good solution. You can read FileBot Groovy Expression Reference Documentation (and then follow all the links) if you want to know everything on a technical level, but this is neither necessary nor recommended.
:idea: Please read the FAQ and How to Request Help.
topbanana
Posts: 34
Joined: 22 Jan 2015, 04:51

Re: Replace characters once for whole filename?

Post by topbanana »

rednoah wrote: 29 Feb 2024, 12:47 The simple version will look more like this:

Format: Select all

{
	(n + ' - '  + s00e00 + ' - ' + t).replace('<':'﹤','>':'﹥',':':'꞉','"':'“','/':'⁄','|':'⼁','?':'?','*':'﹡','\\':'∖')
}
That's much easier to understand!
Thanks!
Post Reply