Page 2 of 2

Re: How about sharing our format expressions?

Posted: 27 Apr 2020, 04:13
by AbedlaPaille
Abed Movies

Code: Select all

E:/{fn =~ /3D/ ? 'Films 3D' : 'Films'}/{norm = {it.upperInitial().replaceTrailingBrackets().replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:|]/, " - ").replaceAll(/[?]/, "!").replaceAll(/[*\s]+/, " ").replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() })}; {info.OriginalLanguage != /en/ ? norm(n) : norm(primaryTitle)}}{info.OriginalName != n && ! (info.OriginalLanguage ==~ /(en|fr)/) ? ' ('+norm(primaryTitle)+')' :""}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""} ({y}){' ['+vf.match(/720[pP]|1080[pP]/)+']'}{video.CodecID =~ /hev1|hevc|HEVC/ ? ' [HEVC]' : ''}/{info.OriginalLanguage != /en/ ? norm(n) : norm(primaryTitle)}{info.OriginalName != n && ! (info.OriginalLanguage ==~ /(en|fr)/) ? ' ('+norm(primaryTitle)+')' :""}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""} ({y}){' [' + fn.matchAll(/UNCENSORED|UNRATED|REMASTERED|EXTENDED|UNCUT|DIRECTOR\'?S[ ._-]CUT|THEATRICAL[ ._-]CUT|ULTIMATE[ ._-]CUT|FINAL[ ._-]CUT|SPECIAL[ ._-]EDITION/)*.upper().sort().join(' ').replaceAll(/[.]/, " ") + ']'}{' ['+vs.match(/BluRay/)+']'}{' ['+vf.match(/720[pP]|1080[pP]/)+']'}{video.CodecID =~ /hev1|hevc|HEVC/ ? ' [HEVC]' : ''}{if (bitdepth == 10) ' [10bit]'}{if (af == (/6ch/)) ' [5.1]'}{" CD$pi"}{'.'+lang}{if (dc > 1) " ($di)"}
  • All movies are in preferred language French except English ones -> English
  • Adds original title if it's neither an english nor french movie
  • Retains quality if 720p/1080p / Retains source if BluRay / Retains bitdepth if 10bit / Retains codec if HEVC / Retains af if 6ch (prints 5.1)
  • Deals with multiple subtitles in same language by adding (1), (2), (3)
  • Retains movie tags like remastered, extended, 3D
  • Special folder for 3D movies
  • Invalid characters replacement
Examples
E:/Films/E.T. The Extra-Terrestrial (1982) [1080p]/E.T. The Extra-Terrestrial (1982) [BluRay] [1080p] [5.1]
E:/Films/Entre Les Murs (2008)/Entre Les Murs (2008)
E:/Films/Four Weddings And A Funeral (1994) [1080p] [HEVC]/Four Weddings And A Funeral (1994) [REMASTERED] [BluRay] [1080p] [HEVC] [10bit] [5.1]
E:/Films/Four Weddings And A Funeral (1994) [1080p] [HEVC]/Four Weddings And A Funeral (1994) [REMASTERED] [BluRay] [1080p] [HEVC] [10bit] [5.1].eng (1)
E:/Films/Four Weddings And A Funeral (1994) [1080p] [HEVC]/Four Weddings And A Funeral (1994) [REMASTERED] [BluRay] [1080p] [HEVC] [10bit] [5.1].eng (2)
E:/Films 3D/How To Train Your Dragon 3D (2010) [1080p]/How To Train Your Dragon 3D (2010) [BluRay] [1080p] [5.1]
Still trying to figure out having collections and movies with a single expression
Don't know how to make custom collections like Pixar, Ghibli, MCU
Haven't managed to transliterate asian titles

Re: How about sharing our format expressions?

Posted: 21 Jun 2020, 07:39
by jebbe

Code: Select all

{['F:', 'G:', 'I:', 'J:', 'L:', 'V:', 'W:', 'Y:'].collect{ (it+'/Movies') as File }.sort{ a, b -> a.exists() <=> b.exists() ?: a.diskSpace <=> b.diskSpace }.last()} ({vf})\{n} ({y}){' ['+fn.replaceAll(/(?i)directors|theatrical|ultimate/,'$0 Cut').matchAll(/OPEN.MATTE|UNRATED|REMASTERED|EXTENDED|UNCUT|DIRECTORS.CUT|THEATRICAL.CUT|ULTIMATE.CUT|SPECIAL.EDITION/).join('][').upperInitial().lowerTrail()+']'} [{vf}] [{ac}{fn.match("-HD.MA.")+af}]/{n} ({y}) {vc}{" (CD$pi)"}{' '+lang}
Here is what I use and am still trying to figure out how to make it so if it finds Open.Matte or Special.Edition in the title and places it in the title, it removes the . between the two words. I can of course do it manually but unsure how to do this with the code. Most of what I use is pieces of many of peoples code here that I've Frankensteined together for my needs.

Re: How about sharing our format expressions?

Posted: 18 Jul 2020, 03:24
by Baradhur
Here is mine. I've used that one for 2 years now an all my libraries are organized following thing. My model is simple and represents exactly what I need.

Movies

Base format is

Code: Select all

Movie Categorie\Name in french (year) - (director) (VO name if different from french) [Languages] [Resolution, video code, audio codec]
Script

Code: Select all

Films/renamed/{any{genres[0]}{"Unknown"}}/ 
{any{localize.fr.n}{n}}
{(pn >= 2) ? " cd$pi" : ""} 
{"($y)"} 
- {"($director)"} 
{localize.fr.n == primaryTitle ? "" : "(${primaryTitle})"}
{"[${fn.lower().match(/- fr|- vostfr|- multi|\[fr\]|\[vostfr\]|\[multi\]|multi|vostfr/).replace('- ', '')}]"} 
{allOf{"$vf"}{"$vc"}{"$ac"}}
Before

Code: Select all

The.Invisible.Man.2020.MULTi.TRUEFRENCH.1080p.HDLight.x264.AC3-EXTREME.mkv
After

Code: Select all

renamed\Thriller\Invisible Man (2020) - (Leigh Whannell) (The Invisible Man) [multi] [1080p, x264, AC3]

Series
base format is

Code: Select all

TV show\TV Show Season Number\TV Show - SxE - Episode name [languages] [resolution] [codes]
Script

Code: Select all

Renamed/{n}/{n} Saison {s.pad(2)}/{n} - {sxe} - {t} {"[vostfr]"} {"[$vf]"} {allOf{"$vc"}{"$ac"}}
Before

Code: Select all

Brooklyn.Nine-Nine.S07E01.MULTi.720p.WEB.H264-CiELOS.mkv
After

Code: Select all

Renamed\Brooklyn Nine-Nine\Brooklyn Nine-Nine Saison 07\Brooklyn Nine-Nine - 7x01 - Manhunter [vostfr] [720p] [AVC, AAC].mkv

Re: How about sharing our format expressions?

Posted: 04 Dec 2020, 01:14
by xaeiou
Here is my format expression replacing characters illegal on the Windows filesystem with similar looking unicode characters. I don't use Windows, but I do share files from my Linux NAS via samba - this format is necessary for the samba clients to see the filenames correctly, otherwise they will be truncated to 8 character DOS format and are usually impossible to recognise.

It's also possible to have the fileserver make this translation, but I prefer to have filebot do it during renaming then I never have to worry about it again.

This expression includes a prefix with all the replaced characters so you can see how they look on your system font.

Thanks to rednoah for helping me simplify the syntax for this expression.

Code: Select all

'<>:"/\\|?*'.replace(
	'<' : '﹤',
	'>' : '﹥',
	':' : 'ː',
	'"' : '“',
	'/' : '⁄',
	'|' : '⼁',
	'?' : '?',
	'*' : '﹡',
	'\\': '∖'
)

Re: How about sharing our format expressions?

Posted: 24 Aug 2021, 09:09
by WhatTimeDayPlace
Movies with localized title + original and alternative titles

I want to keep movie files
  • in a Plex-compatible format
  • with the localized title leading.
  • In addition the original title should be added in square brackets.
  • If the local title is equal to the original title, then the original title can be dropped.
  • Alternative titles are desirable, too, but only local ones. I don't want all alternative titles world-wide.
In my case "local" is German. So desired example outcomes look like this:
  • Verfluchtes Amsterdam (1988) [Amsterdamned]
  • Wer Gewalt sät... (1971) [Straw Dogs]
  • Lost in Space (1998)
  • Dark Planet / Rebellion (2009) [Obitaemyy Ostrov. Skhvatka, The Inhabited Island 2 / Rebellion]
I lack rule programming skills. Thankfully @rednoah provided the following, which works well for me:

Code: Select all

{ny} { allOf{ primaryTitle }{ localize.en.n }.joiningDistinct(', ', '[', ']'){ n.contains(it) ? null : it } }
Issues I still see are mostly related to shortcomings in TMDB. So that is not related to FileBot or the formatting rule.

The original thread is here: viewtopic.php?f=6&t=12755

Re: How about sharing our format expressions?

Posted: 23 Jan 2022, 16:07
by SnakeBonD
Hi,
For my first message, I would like to thank the FileBot developers for this application, as well as all members of this forum for their sharing of examples. ;)
I spent a lot of time in this forum, because there are many ideas to find a solution for each way to rename media files. :idea:

Here is the way I rename my media files:

MOVIES:
For movies I wanted to classify them in the following order:
By studio (Marvel, Disney, Dreamworks, etc.), by Collection or by genre/
the title of the movie in my language, then in the original language if existing, the year, rating, if audio is not french and have subtitle = [VOSTFR] not subtitle=[VO], resolution and audio channels.

exemple:
_MOVIES\COLLECTION\JAMES─BOND─007\Goldeneye [1995] [6.9★] [tt0113189][HD][5.1].mkv
_MOVIES\GENRE\Action\Sky Hunter [2017] (空天猎) [7.2★] [tt6908536][VO][SD][5.1].mkv
_MOVIES\STUDIO\MARVEL\Avengers L'ère D'ultron [2015] (Avengers Age Of Ultron) [7.3★] [tt2395427][VOSTFR][Full HD][5.1].mkv

Code: Select all

/_MOVIES/
{any
	{ 
	info.productionCompanies*.match(
		/Marvel/ : 'STUDIO/MARVEL',
		/Lucasfilm/ : 'STUDIO/STAR─WARS',
		/DC / : 'STUDIO/DC─COMICS',
		/Disney/ : 'STUDIO/DISNEY',
		/Pixar/ : 'STUDIO/PIXAR',
		/Dreamworks/ : 'STUDIO/DREAMWORKS',
		/Studio Ghibli/ : 'STUDIO/STUDIO─GHIBLI'
		).find()
	}	
	
	{ 'COLLECTION/'+collection
	.replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/)
	.replaceFirst(/^(?i)(Collection of the)\s(.+)/, /$2 Collection/)
	.replaceAll(/ - Saga/, "")
	.replaceAll(/ Collection/, "")
	.replaceAll(/Saga Collection/, "")
	.replaceAll(/[`´‘’ʻ""“”]/, "'")
	.replaceAll(/[:*?"<>|?]/)
	.replaceAll(/[*\s]+/, "─")
	.upper()
	}
	
	{
	def genreOrder = ['Anilation': 1, 'Comedy': 2, 'Horror': 3, 'Science-Fiction': 4, 'Adventure': 5, 'Romance': 6, 'Drama': 7, 'Action': 8].withDefault{ 100 }
	'GENRE/'+genres.toSorted{ genreOrder[it] }[0]
	}
}/

{
	norm = {
		it
		.upperInitial()
		.lowerTrail()
		.replaceTrailingBrackets()
		.replaceAll(/[`´‘’ʻ""“”]/, "'")
		.replaceAll(/[:*?"<>|?]/)
		.replaceAll(':', 'ː')
		.replaceAll(/[?]/, "?")
	}
	; norm(n)
} 
[{y}] 
{if (norm(n) != norm(primaryTitle)) ' ('+norm(primaryTitle)+')'} 
{" ["+rating+"★]"}
{" ["+imdbid+"]"}
{'fr' in text.language ? '[VOSTFR]' : 'VO'}
{vf == /2160p/ ? '[4K]' : vf =~ /1080p/ ? '[Full HD]' : vf =~ /720p/ ? '[HD]' : '[SD]'}[{channels}]
TV SHOW:

For the Series, I classified them by the name of the series + year + number of seasons + number of episodes /
Sub folders with 1 folder by season + number episodes /
Title Serie + Name Episode + if audio is not french and have subtitle = [VOSTFR] not subtitle=[VO], resolution and audio channels.

exemple:
_SERIES\L'AGENCE TOUS RISQUES [1983] [5 Saison, 98 Episodes]\The A-Team [Saison 05-13 épisodes]\L'Agence Tous Risques [1983] - S05E01 - Dishpan Man [SD][2.0].mp4

Code: Select all

/_SERIES/
{
	norm = {
		it
		.upper()
		.replaceTrailingBrackets()
		.replaceAll(/[`´‘’ʻ""“”]/, "'")
		.replaceAll(/[:*?"<>|?]/)
		.replaceAll(':', 'ː')
		.replaceAll(/[?]/, "?")
		.replaceAll(/[*\s]+/, " ")
	}; norm(n)
} [{y}] [{episodelist.season.max()} Saison, {episodelist.count{ it.episode }} Episodes]/
/{localize.english.n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:*?"<>|?]/).upperInitial().replaceTrailingBrackets().lowerTrail().replacePart(', Part $1')} 
[Saison {s.pad(2)}-{episodelist.count{ it.episode && it.season == s }} épisodes]/

{
	norm = {
		it
		.upperInitial()
		.replaceTrailingBrackets()
		.replaceAll(/[`´‘’ʻ""“”]/, "'")
		.replaceAll(/[:*?"<>|?]/)
		.replaceAll(':', 'ː')
		.replaceAll(/[?]/, "?")
		.replaceAll(/[*\s]+/, " ")
	}; norm(n)
} [{y}] 

- {s00e00} - {localize.english.t.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:*?"<>|?]/).lowerTrail().replacePart(', Part $1')} 
{'fr' in text.language ? '[VOSTFR]' : '[VO]'}
{vf == /2160p/ ? '[4K]' : vf =~ /1080p/ ? '[Full HD]' : vf =~ /720p/ ? '[HD]' : '[SD]'}[{channels}]
MUSIC:
For the music I treat them before with musicbrainz, then with mp3tag, then with Filebot.
I classify them in files according to:
File Format (if MP3 -> _MP3 _) / Genre (if no kind -> _No_Genre _) / Artist / Album / Artist - Title [Bitrate] .ext

exemple:
_MUSIC\_MP3_\_NO_GENRE_\ACDC\Acdc - Tnt [128 kbps].mp3
_MUSIC\_MP3_\SERTANEJO\LEANDRO E LEONARDO\TE AMO DEMAIS\Leandro E Leonardo - 002 - Tudo Me Lembra Você [192 kb s].mp3
_MUSIC\_FLAC_\HEAVY METAL\METALLICA\ONE OF 282\Metallica - 001 - Of Wolf And Man [1 048 kb s].flac

Code: Select all

/_MUSIC/{'_'+ext.upper()+'_'}/
{any
	{genre
	.tokenize(',')
	.first()
	.replace(':' : 'ː')
	.replaceAll(/[`´‘’ʻ""“”]/, "")
	.replaceAll(/[.:*?"<>|?]/)
	.replaceAll(/&/,"and")
	.replaceAll(/#/,"number")
	.replaceTrailingBrackets()
	.lowerTrail()
	.upper()
	}
	{'_NO_GENRE_'}
}/
{
	artist
	.replace(':' : 'ː')
	.replaceAll(/[`´‘’ʻ""“”]/, "")
	.replaceAll(/[.:*?"<>|?]/)
	.replaceAll(/&/,"and")
	.replaceAll(/#/,"number")
	.replaceTrailingBrackets()
	.lowerTrail()
	.upper()
}/

{
	album
	.replaceAll(/&/,"and")
	.replaceAll(/#/,"number")
	.replace(':' : 'ː')
	.replaceAll(/[`´‘’ʻ""“”]/, "")
	.replaceAll(/[.:*?"<>|?]/)
	.replaceTrailingBrackets()
	.lowerTrail()
	.upper()
}
/
{
	artist
	.replace(':' : 'ː')
	.replaceAll(/[`´‘’ʻ""“”]/, "")
	.replaceAll(/[.:*?"<>|?]/)
	.replaceAll(/&/,"and")
	.replaceAll(/#/,"number")
	.replaceTrailingBrackets()
	.lowerTrail()
	.upperInitial()
}
{any
	//{media.'part/position_total' == null ? null : '/CD ' + media.'part/position'}
	{' - '+pi.pad(3)+' - '}
	{' - '}
}

{
	t
	.replace(':' : 'ː')
	.replaceAll(/[`´‘’ʻ""“”]/, "")
	.replaceAll(/[.:*?"<>|?]/)
	.replaceAll(/&/,"and")
	.replaceAll(/#/,"number")
	.replaceTrailingBrackets()
	.lowerTrail()
	.upperInitial()
} 
[{audio[0].bitratestring.replace('/', 'p')}]

MY Script I have been working on for years and is pretty close to being perfect for me!

Posted: 11 Mar 2023, 15:14
by cyberdoggy

Code: Select all

{ hd =~ /UHD/ ? 'F:/' : 'I:/' }{ hd =~ /UHD/ ? 'Movies 4K' : 'Movies' } ({ vc?.replace('AVC', 'x264')?.replace('HEVC', 'x265') })/
{az}/
{any{ collection?.replaceFirst(/^(?i)(The|A|An)\s(.+)/, '$2, $1')?.replace(':', ' -') }{''}}/ 
{any{ '[' + ci + ']' }{''}} {n.replaceFirst(/^(?i)(The|A|An)\s(.+)/, '$2, $1').replace(':', ' -')} ({y}) 
{
    def audioFormat = aco.replace('DTS-HD Master Audio','DTS-HD')
                         .replace('Dolby TrueHD with Dolby Atmos','TrueHD')
                         .replace('Dolby Digital Plus with Dolby Atmos', '[Atmos]')
    
    (audioFormat == 'Dolby Digital' || audioFormat == 'Dolby Digital Plus' || audioFormat == 'AAC' || audioFormat == 'HE-AAC') ? '' : audioFormat
} 
{tags*.toUpperCase()} {[vs]}
{file.name.toLowerCase().contains("remux") ? '[REMUX]' : ''} 
{def g = any{group}{fn.match(/[-]([^-]+)$/)[0].substring(1)}{fn.match(/(?:(?<=[-])\w+$)|(?:^\w+(?=[-]))/)}; g ? '[' + g + ']' : ''} 
{["$genre"]}
/{n.asciiQuotes().removeAll(/[,!]/).replace(':', '-')}.{y}
{edition?.toUpperCase() ? '.[' + edition.toUpperCase() + ']' : ''}
{any{ pi }{''} ? '.Part' + pi : ''}{'.'+vf}
{any{ fn.match(/(?i)DS4K/) }{''} ? '.DS4K' : ''}
{hd == 'UHD' ? '.4K' : ''}{hd ? '.'+hd : ''}
{any{ video?.HDR_Format =~ /Dolby Vision/ }{false} ? '.DV' : ''}
{any{ video?.HDR_Format_Compatibility =~ /HDR10\+/ }{false} ? '.HDR10+' : 
 any{ video?.HDR_Format_Compatibility =~ /HDR10/ }{false} ? '.HDR' : '.SDR'}
{bitdepth == 10 ? '.10bit' : ''}.
{
    def tokens = source.tokenize('.')
    def joined = tokens.join('.')
    joined.replaceAll(':', ' -')
}
{file.name.toLowerCase().contains("remux") ? '.REMUX' : ''}
{vc =~ /HEVC|265|AV1/ ? (vc =~ /AV1/ ? '.AV1' : '.x265') : '.x264'}.
{any{ audio[0]?.Format_Commercial }{''}?.with { 
    contains('Atmos') ? 
    replace('Dolby TrueHD with Dolby Atmos','TrueHD.Atmos')
      .replace('Dolby Digital Plus with Dolby Atmos','DDP.Atmos') : 
    replace('Dolby TrueHD','TrueHD')
      .replace('DTS-HD Master Audio','DTS-HDMA')
      .replace('Dolby Digital Plus','DDP')
      .replace('Dolby Digital','DD') 
} + ".${channels}CH"}
{def g = any{group}{fn.match(/[-]([^-]+)$/)[0].substring(1)}{fn.match(/(?:(?<=[-])\w+$)|(?:^\w+(?=[-]))/)}; g ? '-' + g : ''}
Results: Movies 4K (x265)\D\Deadpool Collection\[2] Deadpool 2 (2018) [SUPER DUPER CUT] [BluRay] [Groupname] [Action]\Deadpool.2.2018.[SUPER.DUPER.CUT].2160p.4K.UHD.HDR.10bit.BluRay.x265.DDP.5.1CH-GROUPname

If you use it, change the Drive locations to your storage Drive Locations!

Re: How about sharing our format expressions?

Posted: 07 Apr 2023, 11:09
by shomidamoney
Let me give you a bit of context. For me whenever I get a new file, I put it into a sorting hat folder to rename and sort through the files, from there I put it into the correct places; i.e. Movies, Collections, TV Shows, etc. folders. I have a few different presets I use depending on the situation.

These are my most commonly used.

Basically it renames the file, places it into a folder with the same name, and any other parent folders like collection/season, then places it into my sorting hat folder.

Unsorted TV Shows:

Code: Select all

Sorting Hat/{ny}/Season {s}/{ny.colon(' - ')}{s00e00} - {t.colon(' - ')}{if (edition == '')'' else (' -'+{edition})} [{if (hd == 'UHD')'4k UHD' else if (hd == 'FHD')'1080p FHD' else if (hd == 'HD')'720p HD' else if (hd == 'SD')'480p SD' else ({hd})}{if (hdr == '') '' else({','+hdr})},{acf}]
Example:
From - Breaking.Bad.S02E01.1080p.BluRay.x265-RARBG
To - Sorting Hat/Breaking Bad (2008)/Season 2/Breaking Bad (2008) S02E01 - Seven Thirty-Seven [1080p FHD,AAC5.1]

Unsorted Movies - Collection:

Code: Select all

Sorting Hat/{if (collection == '') '' else (collection.colon(' - ')+'/')}{ny.colon(' - ')}/{ny.colon(' - ')}{if (edition == '')'' else (' - '+{edition})} [{if (hd == 'UHD')'4k UHD' else if (hd == 'FHD')'1080p FHD' else if (hd == 'HD')'720p HD' else if (hd == 'SD')'480p SD' else ({hd})}{if (hdr == '') '' else({','+hdr})},{acf}]
Example:
From - Avatar.2009.EXTENDED.1080p.BluRay.x265-RARBG.mp4
To - Sorting Hat/Avatar (2009)/Avatar (2009) - Extended [1080p FHD,AAC5.1].mp4

Unsorted Movies - No Collection: (sometimes I use this if I have existing collection folders; i.e. new movie in series comes out)

Code: Select all

Sorting Hat/{ny.colon(' - ')}/{ny.colon(' - ')}{if (edition == '')'' else (' - '+{edition})} [{if (hd == 'UHD')'4k UHD' else if (hd == 'FHD')'1080p FHD' else if (hd == 'HD')'720p HD' else if (hd == 'SD')'480p SD' else ({hd})}{if (hdr == '') '' else({','+hdr})},{acf}]
Example:
From - Avatar.The.Way.of.Water.2022.2160p.WEB-DL.DDP5.1.Atmos.DV.HDR10.HEVC-CMRG.mkv
To - Sorting Hat/Avatar - The Way of Water (2022)/Avatar - The Way of Water (2022) [4k UHD,Dolby Vision,DDPDA5.1].mkv

There's prolly some things I should change but so far this seems to be good. I also have some other simple renaming ones in case I need to do an overhaul of renaming where it keeps the files in its place and just renames it.

Please provide me with any feedback, good or bad.

Re: How about sharing our format expressions?

Posted: 24 Sep 2023, 01:02
by DocShaker
Movies:

Movies in Their Own Folders

Asterix & Obelix The Middle Kingdom (2023) {tmdb-643215}\Asterix & Obelix The Middle Kingdom (2023) {tmdb-643215} [1080p WEB-DL AVC] [WDYM].mkv
Twin Dragons (1992) {tmdb-18764} {edition-International Cut}\Twin Dragons (1992) {tmdb-18764} {edition-International Cut} [1080p BluRay REMUX AVC] [FraMeSToR].mkv
Twin Dragons (1992) {tmdb-18764} {edition-Theatrical Cut}\Twin Dragons (1992) {tmdb-18764} {edition-Theatrical Cut} [1080p BluRay HYBRID REMUX AVC] [FraMeSToR].mkv
Cult of Chucky (2017) {tmdb-393345}\Cult of Chucky (2017) {tmdb-393345} [2160p BluRay REMUX Dolby Vision HEVC] [FraMeSToR].mkv

Code: Select all

{folder}/{n.validateFileName()} ({y}) {" {tmdb-$id}"} { "{edition-${tags[0]}}" }/{n.validateFileName()} ({y}) {" {tmdb-$id}"} { "{edition-${tags[0]}}" } {[fn.match(/REPACK/)]} {[fn.match(/PROPER/)]} [{vf} {vs.replace('Bluray','BluRay').replace('Blu-ray','BluRay').replace('DVD-R','DVD')} {fn.match(/Hybrid/)} {fn.match(/REMUX/)} {hdr} {vcf.replace('MPEG Video','MPEG')}] [{ any{ fn.match(/^\[(.*?)\]/) }{ fn.match(/\[([^\[\]]+)\]+/) }{ fn.match(/[-]([^-]+)$/) }{ group } }]

Movies with no folders:

Asterix & Obelix The Middle Kingdom (2023) {tmdb-643215} [1080p WEB-DL AVC] [WDYM].mkv
Twin Dragons (1992) {tmdb-18764} {edition-International Cut} [1080p BluRay REMUX AVC] [FraMeSToR].mkv
Twin Dragons (1992) {tmdb-18764} {edition-Theatrical Cut} [1080p BluRay HYBRID REMUX AVC] [FraMeSToR].mkv
Cult of Chucky (2017) {tmdb-393345} [2160p BluRay REMUX Dolby Vision HEVC] [FraMeSToR].mkv

Code: Select all

{n.validateFileName()} ({y}) {" {tmdb-$id}"} { "{edition-${tags[0]}}" } {[fn.match(/REPACK/)]} {[fn.match(/PROPER/)]} [{vf} {vs.replace('Bluray','BluRay').replace('Blu-ray','BluRay').replace('DVD-R','DVD')} {fn.match(/Hybrid/)} {fn.match(/REMUX/)} {hdr} {vcf.replace('MPEG Video','MPEG')}] [{ any{ fn.match(/^\[(.*?)\]/) }{ fn.match(/\[([^\[\]]+)\]+/) }{ fn.match(/[-]([^-]+)$/) }{ group } }]

Series Anime/TV with series and season folders:

Series with episode title:

My Unique Skill Makes Me OP Even at Level 1 (2023)\Season 01\My Unique Skill Makes Me OP Even at Level 1 (2023) S01E01 He's a Human That Was Dropped by a Slime [1080p WEB-DL AVC] [ZR].mkv
The Queen's Gambit (2020)\Season 01\The Queen's Gambit (2020) S01E01 Openings [2160p WEB-DL Hybrid Dolby Vision HEVC] [HONE].mkv
Squid Game (2021)\Season 01\Squid Game (2021) S01E01 Red Light, Green Light [2160p WEB-DL HDR10 HEVC] [HBO].mkv
Kuromukuro (2016)\Season 01\Kuromukuro (2016) S01E01 A Rain of Ogres from the Sky [1080p REMUX AVC] [FraMeSToR].mkv

Code: Select all

{folder}/{n.validateFileName()} ({y})/Season {s.pad(2)}/{n.validateFileName()} ({y}) {s00e00} {t.validateFileName()} { "{edition-${tags[0]}}" } {[fn.match(/REPACK/)]} {[fn.match(/PROPER/)]} [{vf} {vs.replace('Bluray','BluRay').replace('Blu-ray','BluRay').replace('DVD-R','DVD')} {fn.match(/Hybrid/)} {fn.match(/REMUX/)} {hdr} {vcf.replace('MPEG Video','MPEG')}] [{ any{ fn.match(/^\[(.*?)\]/) }{ fn.match(/\[([^\[\]]+)\]+/) }{ fn.match(/[-]([^-]+)$/) }{ group } }]

Series without episode title:

My Unique Skill Makes Me OP Even at Level 1 (2023)\Season 01\My Unique Skill Makes Me OP Even at Level 1 (2023) S01E01 [1080p WEB-DL AVC] [ZR].mkv
The Queen's Gambit (2020)\Season 01\The Queen's Gambit (2020) S01E01 [2160p WEB-DL Hybrid Dolby Vision HEVC] [HONE].mkv
Squid Game (2021)\Season 01\Squid Game (2021) S01E01 [2160p WEB-DL HDR10 HEVC] [HBO].mkv
Kuromukuro (2016)\Season 01\Kuromukuro (2016) S01E01 [1080p REMUX AVC] [FraMeSToR].mkv

Code: Select all

{folder}/{n.validateFileName()} ({y})/Season {s.pad(2)}/{n.validateFileName()} ({y}) {s00e00} { "{edition-${tags[0]}}" } {[fn.match(/REPACK/)]} {[fn.match(/PROPER/)]} [{vf} {vs.replace('Bluray','BluRay').replace('Blu-ray','BluRay').replace('DVD-R','DVD')} {fn.match(/Hybrid/)} {fn.match(/REMUX/)} {hdr} {vcf.replace('MPEG Video','MPEG')}] [{ any{ fn.match(/^\[(.*?)\]/) }{ fn.match(/\[([^\[\]]+)\]+/) }{ fn.match(/[-]([^-]+)$/) }{ group } }]


Series Anime/TV with no series and season folders:

Series with episode title:

My Unique Skill Makes Me OP Even at Level 1 (2023) S01E01 He's a Human That Was Dropped by a Slime [1080p WEB-DL AVC] [ZR].mkv
The Queen's Gambit (2020) S01E01 Openings [2160p WEB-DL Hybrid Dolby Vision HEVC] [HONE].mkv
Squid Game (2021) S01E01 Red Light, Green Light [2160p WEB-DL HDR10 HEVC] [HBO].mkv
Kuromukuro (2016) S01E01 A Rain of Ogres from the Sky [1080p REMUX AVC] [FraMeSToR].mkv

Code: Select all

{n.validateFileName()} ({y}) {s00e00} {t.validateFileName()} { "{edition-${tags[0]}}" } {[fn.match(/REPACK/)]} {[fn.match(/PROPER/)]} [{vf} {vs.replace('Bluray','BluRay').replace('Blu-ray','BluRay').replace('DVD-R','DVD')} {fn.match(/Hybrid/)} {fn.match(/REMUX/)} {hdr} {vcf.replace('MPEG Video','MPEG')}] [{ any{ fn.match(/^\[(.*?)\]/) }{ fn.match(/\[([^\[\]]+)\]+/) }{ fn.match(/[-]([^-]+)$/) }{ group } }]

Series without episode title:

My Unique Skill Makes Me OP Even at Level 1 (2023) S01E01 [1080p WEB-DL AVC] [ZR].mkv
The Queen's Gambit (2020) S01E01 [2160p WEB-DL Hybrid Dolby Vision HEVC] [HONE].mkv
Squid Game (2021) S01E01 [2160p WEB-DL HDR10 HEVC] [HBO].mkv
Kuromukuro (2016) S01E01 [1080p REMUX AVC] [FraMeSToR].mkv

Code: Select all

{n.validateFileName()} ({y}) {s00e00} { "{edition-${tags[0]}}" } {[fn.match(/REPACK/)]} {[fn.match(/PROPER/)]} [{vf} {vs.replace('Bluray','BluRay').replace('Blu-ray','BluRay').replace('DVD-R','DVD')} {fn.match(/Hybrid/)} {fn.match(/REMUX/)} {hdr} {vcf.replace('MPEG Video','MPEG')}] [{ any{ fn.match(/^\[(.*?)\]/) }{ fn.match(/\[([^\[\]]+)\]+/) }{ fn.match(/[-]([^-]+)$/) }{ group } }]

Re: How about sharing our format expressions?

Posted: 18 May 2024, 13:26
by 619annamalc
I've been using Filebot for about 3 years now, and it has been a game changer with organizing files. I'm still learning and messing with it, and the team here is amazing with helping and explaining. I have used a combination of Plex, Embi, and Jellyfin to host different files, and these formats have not caused issues with any of them. After reading through many forums, I have compiled the following formats which have helped me tremendously:

Movie Code v1. This uses TMDB Collections to organize movies into folders, and adds the movie version tags to folder and file name (i.e. remastered, extended, unrated, etc.):

Format: Select all

{collection+'/'}{n} ({y}) {' (' + fn.matchAll(/extended|uncensored|uncut|directors[ ._-]cut|remastered|unrated|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, " ") + ')'} {"{imdb-$imdbid}"} / {n} ({y}) {"[$vf $vc $ac $af]"}{"{edition-${tags.first()}}"}{subt}

Movie Code v2. This code uses the same code as v1, but will add Language tags to the folder name based on the number of audio streams found in the file (i.e. more than 3 streams = Multi Audio, 2 streams = Dual Audio, 1 stream that is not English will use ISO3 tags, ex. JPN, KOR, RUS). I use this for Foreign and Anime:

Format: Select all

{collection+'/'} {n} ({y}) {' (' + fn.matchAll(/extended|uncensored|uncut|directors[ ._-]cut|remastered|unrated|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, " ") + ')'} {"{imdb-$imdbid}"} {audioLanguages.size() > 2 ? ' (Multi Audio)' : audioLanguages.size() > 1 ? ' (Dual Audio)' : audioLanguages =~ /eng/ ? null : audioLanguages.ISO3.joining(', ', ' (', ')').upper()} / {n} ({y}) {"[$vf $vc $ac $af]"}{" {edition-${tags.first()}}"}{subt}

TV Code v1. Basic code which will generate show name, season folder, and episode format.

Format: Select all

{n} ({y}) {"{tmdb-$tmdbid}"}/Season {s}/{s00E00} - {t} {"[$vf $vc $ac $af]"}{subt}

TV Code v2. This uses the same base code as v1, but I added the Language tags. This has been very helpful with Foreign and Anime.

Format: Select all

{n} ({y}) {"{tmdb-$tmdbid}"} {audioLanguages.size() > 2 ? ' (Multi Audio)' : audioLanguages.size() > 1 ? ' (Dual Audio)' : audioLanguages =~ /eng/ ? null : audioLanguages.ISO3.joining(', ', ' (', ')').upper()} / Season {s}/{s00E00} - {t} {"[$vf $vc $ac $af]"}{subt}

Re: How about sharing our format expressions?

Posted: 27 Dec 2024, 16:37
by Punx
Since my native language is German, this is all translated via Deepl.

I have been using Filebot since the beginning and have always tried new formats
in the end I ended up here.

I myself use the following string for my movies


Movie

Format: Select all

{drive}
/Movies/
/{HD}
/{localize.de.collection.ascii().validateFileName().replace('Collection','Filmreihe') + '/' + "Film " + ci.pad(2) + '  ' }
/{localize.de.plex.name.ascii().validateFileName()} {tags*.toUpperCase()}
/{localize.de.plex.name.ascii().validateFileName()} {tags*.toUpperCase()}
{' DISC ' +pi}
{'.'+fn.match(/forced/)}
{'.'+fn.match(/DUBTITLE/)}
{'.'+fn.match(/closedcaption/)}
{'.'+fn.match(/STRIPPED_SDH/)}
{'-'+fn.match(/mediainfo/)}
{ '.' + lang.ISO3 }
Result
Collection

Code: Select all

/Movies/FHD/Blade Filmreihe/Film 01/Blade (1998) [UNCUT]/Blade (1998) [UNCUT]
Seperate Movie with Tags

Code: Select all

/Movies/UHD/Die Jugger - Kampf der Besten (1989) [UNRATED]/Die Jugger - Kampf der Besten (1989) [UNRATED]
Movies without tags

Code: Select all

/Movies/FHD/Woody, der Ungluecksrabe (1969)/Woody, der Ungluecksrabe (1969)
/Movies/SD/Blood and Bones (2004)/Blood and Bones (2004)
for TV series

Format: Select all

{drive}
/TV Shows/
{~plex.year
% { " [$edition]" }
%{' ★' + tags.first() + '★ '} 
% {' Part '+pi}
% {'.'+fn.match(/forced/)}
% {'-'+fn.match(/mediainfo/)}
% {'.'+fn.match(/DUBTITLE/)}
% {'.'+fn.match(/closedcaption/)}
% {'.'+fn.match(/STRIPPED_SDH/)}
% {'.' + lang.ISO3}}
Result

Code: Select all

/TV Shows/Prinzessin Fantaghirò (1991)/Season 01/Prinzessin Fantaghirò (1991) - S01E01 - Die rebellische Prinzessin
/TV Shows/Prinzessin Fantaghirò (1991)/Season 02/Prinzessin Fantaghirò (1991) - S02E01 - Die schwarze Hexe
usw.

For Music

Format: Select all

{drive}/Music/{'### ' +EXT.upper()+ ' ###'}/
{if (media.'Album/Performer'!=null && (media.'Album/Performer'!=media.'Performer')) return (media.'Performer'!=n?n+'/':media.'Album/Performer'+'/') else n+'/'}\
/{if (media.'Original/Released_Date'!=null||media.'Original/Released_Date'!=Y) return (media.'Original/Released_Date'!=null?media.'Original/Released_Date'.truncate(4):Y)+'' else (Y!=null?Y+'':date.truncate(4)+'')}
/{album.replace(/:/,/,/).replaceAll(/"|`/,/'/)}
{if (media.'musicbrainz.album.type'!=null&&media.'musicbrainz.album.type'=~"/") return (album=~/Live|LIVE|live|Soundtrack|Best Of|best of|greatest|Remix|remix|Collection/?'':' - '+(media.'musicbrainz.album.type'.upperInitial().split("/")[1])) else (album=~/ EP/||media.'musicbrainz.album.type'=="album"||"other"?'':' - '+media.'musicbrainz.album.type'.upper())} 
{media.'Part/Position_Total'<'2' ? "" : ' ('+media.'Part/Position_Total'+'CDs)'}
{media.'part/position'==null||media.'Part/Position_Total'<'2' ? "" : '/CD'+media.'part/position'}/
{ if (music.medium && music.mediumCount > 1) "CD$music.medium/" }/{pi.pad(2)+'. '}
{media.'Album/Performer'==media.'Performer' ? "" : (media.'Performer').replaceAll('/',', ')+' - '}
{t.replace(/:/,/,/).replaceAll(/"|`/,/'/)}
Result

Code: Select all

Music/### MP3 ###/AC DC/1988/Blow Up Your Video/05. Kissin' Dynamite
\Music\### FLAC ###\Gina Lollobrigida Pat Boone\2023\That's Amore\01. Pat Boone Gina Lollobrigida - That's Amore

I don't need audio or video format info
Plex shows me what I need anyway :)

Re: How about sharing our format expressions?

Posted: 18 Jan 2025, 11:19
by DonaldFaQ
GERMAN Release Tags. All Spaces and illegal symbols changed with "." and no German letters still "Ä,Ö,Ü,ß".

Movie Line for DV / HDR10 Remux:
Example:

Code: Select all

Toedliches.Kommando.The.Hurt.Locker.2008.German.DL.2160p.UHD.BluRay.DV.HDR.HEVC.Remux-QfG

Format: Select all

{n.removeIllegalCharacters().colon('.').slash('.').replaceAll('-', '.').replaceAll('&', 'und').replaceAll('ß', 'ss').replaceAll('ä', 'ae').replaceAll('Ä', 'Ae').replaceAll('ü', 'ue').replaceAll('Ü', 'Ue').replaceAll('ö', 'oe').replaceAll('Ö', 'Oe').space('.').removeAll(/[?!§%(),;'`´‘’ʻ""“”]/)}.{y}.German.DL.{vf}.UHD.BluRay.DV.HDR.HEVC.Remux-{group}
TV-Show Line for DV / HDR10 Remux:
Example:

Code: Select all

Westworld.S01E01.Das.Original.German.DL.2160p.UHD.BluRay.DV.HDR.HEVC.Remux-QfG

Format: Select all

{n.removeIllegalCharacters().colon('.').slash('.').replaceAll('-', '.').replaceAll('&', 'und').replaceAll('ß', 'ss').replaceAll('ä', 'ae').replaceAll('Ä', 'Ae').replaceAll('ü', 'ue').replaceAll('Ü', 'Ue').replaceAll('ö', 'oe').replaceAll('Ö', 'Oe').space('.').removeAll(/[?!§%(),;'`´‘’ʻ""“”]/)}.{s00e00}.{t.removeIllegalCharacters().colon('.').slash('.').replaceAll('-', '.').replaceAll('&', 'und').replaceAll('ß', 'ss').replaceAll('ä', 'ae').replaceAll('Ä', 'Ae').replaceAll('ü', 'ue').replaceAll('Ü', 'Ue').replaceAll('ö', 'oe').replaceAll('Ö', 'Oe').space('.').removeAll(/[?!§%(),;'`´‘’ʻ""“”]/)}.German.DL.{vf}.UHD.BluRay.DV.HDR.HEVC.Remux-{group}

"The Beast" My Latest and Greatest Script

Posted: 18 May 2025, 01:56
by cyberdoggy
This may not be for everyone... But this is basically my Super Beast Script.

Code: Select all

{def get={c->try{def v=c();v==null?null:v.toString()}catch(e){null}}
def getList={c->try{def v=c();v==null ? [] : v instanceof List?v:[v]}catch(e){[]}}
def nrm={s->s?.toString()?.toUpperCase()?.replaceAll(/[.\s]+/,' ')?.trim()?:''}
def stripDot={s->s?.replaceAll(/\.+$/,'')?.replaceAll(/^\.+/,'')?:''}
def isJunk={s->if(!s)return false;if(s.count('.')>3)return true;def u=s.toUpperCase();return u.matches(/.*(X264|X265|X266|H\.?264|H\.?265|HEVC|AVC1?|AV1|VP9|XVID|DIVX|MPEG-?2|VC-?1).*/)||u.matches(/.*(E-?AC-?3|AC-?3|DDP|DD\+|DTS(-?HD)?(\.?MA)?|TRUEHD|AAC|ATMOS).*/)||u.matches(/.*(SDR|HDR10\+?|HDR|DV|DOLBY ?VISION).*/)||u.matches(/.*[0-9]{1,2}BIT.*/)||u.matches(/.*(480P|576P|720P|1080P|2160P|4320P).*/)||u.matches(/.*(WEB-?DL|WEBRIP|BLU-?RAY|BDRIP|BRRIP|HDTV|DVDRIP|REMUX).*/)}
def title=get({n})?:'',year=get({y})?:'',fnRaw=get({fn})?:'',collectionRaw=get({collection})?:''
def cT={s->s?.replaceFirst(/^(?i)(The|A|An)\s+(.+)/,'$2, $1')?.replaceAll('[:/\\\\\\?*"<>|]','-')?.replaceAll(/\s*-\s*/,' - ')?:''}
def cS=cT(collectionRaw)
def groupName=null;def m=fnRaw=~/(?i)-([^-]+)$/
if(m){groupName=m[0][1];groupName=groupName?.replaceAll(/[\[\]]/,'')?.replaceAll(/\s*-\s*/,'-')?.trim()?.with{it=='null'?null:it}}
if(!groupName||isJunk(groupName)){groupName=get({group});if(groupName){groupName=groupName?.replaceAll(/[\[\]]/,'')?.replaceAll(/\s*-\s*/,'-')?.trim()?.with{it=='null'?null:it};if(groupName&&isJunk(groupName))groupName=null}}
def grpTag=groupName?"[${groupName}]":"";def grpHyp=groupName?"-${groupName}":""
def vH=get({video?.height instanceof List?video?.height.find{it}:video?.height})?.toInteger()
def vcRaw=(get({vc})?:'').toUpperCase()
def vfB=get({vf})?:'',hdRaw=get({hd})?:''
def is4K=(get({vk})=='4K'||vfB=='2160p'||hdRaw?.toUpperCase()?.contains('UHD')||(vH&&vH>=2160))
def codecB=(vcRaw=~/AV1/)?'AV1':(vcRaw=~/HEVC|265/)?'x265':(vcRaw=~/AVC|264/)?'x264':(vcRaw=~/VP9/)?'VP9':(vcRaw=~/VC[\s\-]?1/)?'VC1':(vcRaw=~/XVID|DIVX/)?'XviD':(vcRaw=~/MPEG[\s\-]?2/)?'MPEG2':''
def dL='N',root="${dL}:/"+(codecB=='AV1'?"Movies (AV1)":(is4K?"Movies 4K":"Movies (${codecB?:'Other'})"))
def azF=get({az})?:'',colF=cS&&cS!='null'?cS:'',ciT=get({ci?"[$ci]":''})?:''
def editionTag=get({edition})?:''
if(editionTag&&isJunk(editionTag))editionTag=''
def mTags=getList({tags}).collect{nrm(it)}.findAll{it&&!isJunk(it)}
def aTags=mTags.findAll{it&&it!='REMASTERED'}.unique().with{l->l.findAll{t->!l.any{o->o!=t&&o.startsWith(t)}}}
def tagParts=[];if(editionTag)tagParts<<editionTag;tagParts.addAll(aTags);tagParts=tagParts.unique{it.toString().toUpperCase()}
def tagFld=tagParts?tagParts.collect{" [$it]"}.join(''):''
def tagFil=tagParts?tagParts.collect{it.replaceAll(' ','.')}.join('.'):''
def tYB=(title&&year)?"${title} (${year})${tagFld}":(title?title+tagFld:(year?"(${year})${tagFld}":''))
def titleYr=(ciT?ciT+' ':'')+tYB
def tLS=getList({tags}).join(' ').toUpperCase(),fU=fnRaw.toUpperCase()
def hasTag={w->fU.contains(w)||tLS.contains(w)}
def rep=hasTag('REPACK'),repTag=rep?' [REPACK]':'',repFilTag=rep?'REPACK':''
def isInt=hasTag('INTERNAL'),intTag=isInt?' [INTERNAL]':'',intFilTag=isInt?'INTERNAL':''
def isProp=hasTag('PROPER'),propTag=isProp?' [PROPER]':'',propFilTag=isProp?'PROPER':''
def isRemux=fnRaw?.toLowerCase()?.contains('remux')||tLS.contains('REMUX')
def rmT=isRemux?'[REMUX]':'',rmFi=isRemux?'REMUX':''
def genreVal=get({genre})?:'',genB=genreVal?"[${genreVal}]":''
def aTit=get({n})?:'',aTitPer=(aTit&&year?"${aTit} ${year}":(aTit?:year?:'')).replaceAll(/ - /,'.-.').replaceAll(/ /,'.')
def hdrVal=get({hdr})?:'';def doviVal=get({dovi})?:''
def fnUp=fnRaw.toUpperCase()
def hdrCore=hdrVal.replaceAll(/DV[+]?/,'')
if(!hdrCore.contains('+')&&(fnUp.contains('HDR10+')||fnUp.contains('HDR10PLUS')||fnUp.contains('HDR10.PLUS')))hdrCore='HDR10+'
def hdrT='SDR'
def plusFix={h->h.replaceAll(/[+](?!$)/,'.')}
if(doviVal){def cleanHdr=stripDot(plusFix(hdrCore));if(!cleanHdr&&vfB=='2160p'&&codecB in ['x265','VP9','AV1'])cleanHdr='HDR';hdrT=cleanHdr?"DV.${cleanHdr}":"DV"}
else if(hdrCore){hdrT=stripDot(plusFix(hdrCore))}
if(!doviVal&&!hdrCore&&vfB=='2160p'&&codecB in ['x265','VP9','AV1'])hdrT='HDR'
def bitdRaw=get({bitdepth});def bitdB=(bitdRaw&&(bitdRaw=='10'||bitdRaw=='12')&&(hdrT=='SDR'||hdrT=='HDR'))?"${bitdRaw}bit":''
def aCodecFmt=get({acf})?:'';def aCodecRaw=get({aco})?:'';def aChan=get({channels})?:''
def aCodecDisplay='';def aFmt='';def rawUpper=aCodecRaw.toUpperCase();def fmtUpper=aCodecFmt.toUpperCase()
def rawNorm=rawUpper.replaceAll('[-\\s]','');def fmtNorm=fmtUpper.replaceAll('[-\\s]','')
if(rawUpper.contains('DOLBY DIGITAL PLUS')||rawNorm.contains('EAC3')||fmtNorm.contains('DDP')||fmtNorm.contains('DD+')||fmtNorm.contains('EAC3')){aCodecDisplay='EAC3';aFmt='DDP'}
else if(rawUpper.contains('DOLBY DIGITAL')||rawNorm.contains('AC3')||fmtNorm.contains('AC3')){aCodecDisplay='AC3';aFmt='DD'}
else if(rawUpper.contains('DTS-HD MA')||fmtUpper.contains('DTS-HD MA')||rawNorm.contains('DTSHDMA')){aCodecDisplay='DTS-HD MA'}
else if(rawUpper.contains('DTS')||fmtUpper.contains('DTS')){aCodecDisplay='DTS'}
else if(rawUpper.contains('TRUEHD')||fmtUpper.contains('TRUEHD')){aCodecDisplay='TrueHD'}
else if(rawUpper.contains('AAC')||fmtUpper.contains('AAC')){aCodecDisplay='AAC'}
def aAtmos=(rawUpper.contains('ATMOS')||fmtUpper.contains('ATMOS'))?'Atmos':'';def atT=aAtmos?'[ATMOS]':''
def sourceVal=get({source})?:''
if(!sourceVal){def fUp=fnRaw.toUpperCase();if(fUp.contains('WEB-DL')||fUp.contains('WEBDL'))sourceVal='WEB-DL';else if(fUp.contains('WEBRIP'))sourceVal='WEBRip';else if(fUp.contains('BLU-RAY')||fUp.contains('BLURAY')||fUp.contains('BDRIP'))sourceVal='BluRay';else if(fUp.contains('BRRIP'))sourceVal='BRRip';else if(fUp.contains('HDTV'))sourceVal='HDTV';else if(fUp.contains('DVDRIP')||fUp.contains('DVD'))sourceVal='DVD'}
def sFT=sourceVal?"[${sourceVal}]":'';def sFi=sourceVal?:''
def isShout=(collectionRaw=~/(?i)Shout\s*Factory/)||tLS.contains('SHOUT FACTORY')||(fnRaw=~/(?i)Shout\s*Factory/);def shFT=isShout?'[Shout Factory]':''
def fldExP=[];fldExP<<titleYr;if(repTag)fldExP<<repTag;if(intTag)fldExP<<intTag;if(propTag)fldExP<<propTag;if(rmT)fldExP<<rmT;if(sFT)fldExP<<sFT;if(vfB)fldExP<<"[${vfB}]";if(hdrT)fldExP<<"[${hdrT}]";if(aCodecDisplay)fldExP<<"[${aCodecDisplay}]";def audioDisplay=aFmt?"${aFmt}.${aChan}":aChan;if(audioDisplay)fldExP<<"[${audioDisplay}]";if(atT)fldExP<<atT;if(grpTag)fldExP<<grpTag;if(genB)fldExP<<genB;if(shFT)fldExP<<shFT
def fldName=fldExP.findAll{it&&it!=''}.join(' ').replaceAll(/ +/,' ').trim()
def fnParts=[(aTitPer?:'')];if(tagFil)fnParts<<tagFil;if(repFilTag)fnParts<<repFilTag;if(intFilTag)fnParts<<intFilTag;if(propFilTag)fnParts<<propFilTag;if(rmFi)fnParts<<rmFi;if(vfB)fnParts<<vfB;if(is4K)fnParts<<'4K.UHD';if(sFi)fnParts<<sFi;if(hdrT)fnParts<<hdrT;if(codecB)fnParts<<codecB;if(bitdB)fnParts<<bitdB;if(aCodecDisplay)fnParts<<aCodecDisplay;if(aFmt)fnParts<<aFmt;def aChanClean=aChan.replaceAll(/[^0-9.]/,'');if(aChanClean)fnParts<<(aChanClean+'CH');if(aAtmos)fnParts<<aAtmos
def nP={p->p?.toString()?.trim()?.replaceAll(/^\.+|\.+$/,'')?.replaceAll(/ +/,' ')?:''}
def fName=(fnParts.collect{nP(it)}.findAll{it}.join('.').replaceAll(/\.{2,}/,'.').replaceAll(/^\.+|\.+$/,'')?:'')+grpHyp
def sC={s->s?.replaceAll(/:/,' ')?.replaceAll(/[?!|]/,'')}
fldName=sC(fldName);fName=sC(fName);colF=sC(colF);azF=sC(azF)
return [root,azF,colF,fldName,fName].findAll{it&&it!=''}.join('/')}
**** REMEMBER: Make sure to change your Destination Drive to what you need. This script includes my locations!

Results should output similar to this:
N:/Movies 4K/D/Deadpool Collection/[2] Deadpool 2 (2018) [Super Duper Cut] [UNRATED] [BluRay] [2160p] [HDR10] [EAC3] [DDP.7.1] [GROUP] [Action]/Deadpool.2.2018.Super.Duper.Cut.UNRATED.2160p.4K.UHD.BluRay.HDR10.x265.EAC3.DDP.7.1CH-GROUP