How about sharing our format expressions?

All about user-defined episode / movie / file name format expressions
User avatar
rednoah
The Source
Posts: 22899
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

How about sharing our format expressions?

Post by rednoah »

:idea: Please read the FAQ and How to Request Help.
User avatar
rednoah
The Source
Posts: 22899
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Common Naming Schemes

Post by rednoah »

⭑⭑ A more beginner-friendly set of format examples and snippets is being curated via format.md on GitHub. ⭑⭑


TV Shows & Anime

The most simple s00e00 scheme to get you started

Format: Select all

{n} - {s00e00} - {t}
A simple "rename & organize into folders" scheme plus zero-padding for the season folder and language tags for subtitle names

Format: Select all

X:/TV Shows/{n}/Season {s.pad(2)}/{n} - {s00e00} - {t}{'.'+lang}
Similar to the default s00e00 format, but automatically clean up brackets (e.g. The Office (UK) => The Office), normalize apostrophes, don't allow ALL UPPER CASE WORDS (change to All Upper Case Words), replace part information "Pilot (1..n)" to "Pilot, Part 1..n"

Format: Select all

{n.replaceTrailingBrackets()} - {s00e00} - {t.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’ʻ]/, "'").lowerTrail().replacePart(', Part $1')}
Use series name, SxE numbering, codec information and crc32 checksum

Format: Select all

{n.space('_')}_-_{sxe}_[{resolution}_{vc}_{ac}][{crc32}]
Date pattern adding the week day localized to your system language:

Format: Select all

{n} [{airdate.format("yyyy.MM.dd, EEEE", Locale.getDefault())}] {t}
Basic S00E00 format without spaces. Anime episodes without season will default to season 01. This one is supposed to work very well with XBMC:

Format: Select all

{n.space('.')}.S{(episode.season ? s : 1).pad(2)}E{e.pad(2)}.{t.space('.')}
Organize episodes into "Season N" folders with specials being organized into folder "Specials" named as Season 0. Also great for XBMC:

Format: Select all

X:/TV Shows/{n}/{episode.special ? 'Special' : 'Season '+s}/{n} - {episode.special ? 'S00E'+special.pad(2) : s00e00} - {t}

Movies & Subtitles

Movie (Year) adding part index (for multi-part movies) and language code (for subtitle files)

Format: Select all

{n} ({y}){' CD'+pi}{'.'+lang}
A simple "rename & organize into folders" scheme

Format: Select all

X:/Movies/{n} ({y})/{n} ({y}){' CD'+pi}
Special case to add ".CD1" to .nfo files that belong to a multi-CD set (e.g. movie-cd1.avi, movie-cd1.nfo, movie-cd2.avi, ...) as required by HTPC software like YAMJ/Popcornhours's NMJ.

Format: Select all

{n} ({y}){' CD'+pi}{if (ext == 'nfo' && folder.list().find{it =~ /(?i:CD\d+)/}) '.CD1'}
Only organize into folders but do not change filenames.

Format: Select all

X:/Movies/{n} ({y})/{fn}
Organize movies into folders but keep files on the same drive

Format: Select all

{file.path[0]}:/Movies/{n} ({y})/{n} ({y}){' CD'+pi}
Movie name/year and genres followed by the first three actors names.
=> Avatar (2009) [Action, Adventure, Fantasy, Science Fiction] - Sam Worthington, Zoe Saldana, Sigourney Weaver

Format: Select all

{n} ({y}) {genres} - {actors.take(3).join(', ')}
Organize movies into collections and folders and add resolution and audio codec/channels to the filename. Preserve video source (e.g. BluRay) and 3D labels in the filename.
=> X:/Movies/Avatar Collection/Avatar (2009) [BluRay]/Avatar (2009) [3D, 720p, AAC, 6ch]

Format: Select all

X:/Movies/{collection+'/'}{n} ({y}){'['+source+']'}/{n} ({y}) [{fn.match(/3D/)+', '}{vf}, {ac}, {af}]
Organize and separate Movies and 3D Movies.
=> 3D Movies/Avatar (2009) [3D] [H-SBS]/Avatar (2009) (720p) H-SBS.mp4

Format: Select all

{fn =~ /3D/ ? '3D Movies' : 'Movies'}/{n} ({y}){fn =~ /3D/ ? ' [3D] [H-SBS]' : ''}/{n} ({y}) ({vf}){fn =~ /3D/ ? ' H-SBS' : ''}{' CD'+pi}

Advanced Format Expressions

Here's some examples and snippets for more advanced naming logic. Modify to your needs. Anything is possible. ;)

Sort into drive with the most free space:

Format: Select all

{['C:', 'D:', 'E:'].collect{ (it+'/TV/'+n) as File }.sort{ a, b -> a.exists() <=> b.exists() ?: a.diskSpace <=> b.diskSpace }.last()}/{plex.name}
This format will always evaluate to a path to the drive with the most free space, unless the series folder already exists on one of the drives in which case it'll prefer the existing one.

Sort into multiple drives based on initial letter:

Format: Select all

{n =~ /^(?i)[0-9a-f]/ ? 'X' : n =~ /^(?i)[g-t]/ ? 'Y' : 'Z'}:/TV/{n}/{plex.name}
Drive X if first letter of {n} matches [0-9a-f], Drive Y for [g-t] and Drive Z for everything else.



Automated Media Center Default Formats

These are the default format expressions used in the AMC script and will create a structure that should work very well with any media center.

TV Series

Format: Select all

TV Shows/{n}/{episode.special ? 'Special' : 'Season '+s.pad(2)}/{n} - {episode.special ? 'S00E'+special.pad(2) : s00e00} - {t.replaceAll(/[`´‘’ʻ]/, /'/).replaceAll(/[!?.]+$/).replacePart(', Part $1')}{'.'+lang}
Anime

Format: Select all

Anime/{primaryTitle}/{primaryTitle} - {sxe} - {t.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’ʻ]/, /'/).replacePart(', Part $1')}
Movie

Format: Select all

Movies/{n} ({y})/{n} ({y}){' CD'+pi}{'.'+lang}
Music

Format: Select all

Music/{n}/{album+'/'}{pi.pad(2)+'. '}{artist} - {t}
Unsorted

Format: Select all

Unsorted/{relativeFile}

Note: If you're passing any format expression in via command-line you must escape it correctly (e.g. replace all " in the format with \" and on Linux/Mac you need to take care of $ as well).
:idea: Please read the FAQ and How to Request Help.
Okam
Posts: 1
Joined: 24 Apr 2012, 00:49

Re: How about sharing our format expressions?

Post by Okam »

Spent a bit of time on my format expression (especially since it took me a while to figure out that by putting the brackets INSIDE the {} instead of outside that it would not append empty []'s to my file names if the bindings were undefined XP) so I thought I should share it here so others can see it. Anyways, here you go:

Code: Select all

F:/{n}{"/Season $s"}/{n} - {s}{e.pad(2)} - {t}{" [$airdate.year]"}{" [$vf]"}{" [$source]"}{" [$vc]"}{" [$ac]"}{" [$group]"}
This takes my files, organizes them by series and season, then renames them and appends the info tags ONLY if the info exists.

Example 1 (source and group unknown):
American Dad - 101 - Threat Levels.avi
became
F:\American Dad!\Season 1\American Dad! - 101 - Pilot [2005] [384p] [XviD] [MP3].avi

Example 2 (all info known):
american.horror.story.s01e01.720p.hdtv.x264-orenji.mkv
became
F:\American Horror Story\Season 1\American Horror Story - 101 - Pilot [2011] [720p] [HDTV] [x264] [AC3] [ORENJi].mkv

NOTE 1: For the source and group bindings to work the file name must already include them in some form so that FileBot can read and parse the data from it.

NOTE 2: For the video format, video codec, and audio codec bindings to work you need to have MediaInfo installed and working. Reference
Q: Why does MediaInfo not work? I'm running on 64-bit Windows and installed FileBot x64?
A: If you're on 64-bit Windows but are actually running a 32-bit Java runtime, the whole java process will be in 32-bit compability mode, so the mediainfo native library also has to be the 32-bit version. Just install FileBot x86 instead, or replace mediainfo.dll with the 32-bit version.
from the FAQ if you are having trouble.

Hope this helps!

edit: fixed code to use the year the episode aired rather than the series premier year returned by the {y} binding.
Igor
Posts: 14
Joined: 27 Jun 2012, 21:04

Re: How about sharing our format expressions?

Post by Igor »

Here's the format expression I use. It's very similar to scene formatting standard but is cleaned up a bit.

Code: Select all

{n.upperInitial().space('.').replaceAll(/[,]+/)}.{s00e00}.{t.upperInitial().space('.').replaceAll(/[,]+/)}{'.'+vf.match(/720[pP]|1080[pP]/)}{".$source"}{".$vc"}{'-'+fn.match(/(?:(?<=[-])\w+$)|(?:^\w+(?=[-]))/)}
It does the following:

1. Replaces all spaces in the series name with periods, removes all commas and capitalizes the first letter of every word.
2. Appends season and episode number in format S00E00.
3. Replaces all spaces in the episode name with periods, removes all commas and capitalizes the first letter of every word.
4. Appends video format ONLY if 720p or 1080p.
5. Appends source if available.
6. Appends video codec if available.
7. Appends group if the original file is in the format "blahblah-group.avi" or "group-blahblah.avi". (Change to {"-$group"} to match to filebot group list instead)


Example 1

Before:
chuck.101.dvdrip-rwd.avi

After:
Chuck.S01E01.Chuck.Versus.The.Intersect.DVDRip.XviD-rwd.avi

Example 2

Before:
runner-batman-s01e01.avi

After:
The.Batman.S01E01.The.Bat.In.The.Belfry.XviD-runner.avi

Example 3

Before:
aaf-watxm.s01e01.720p.mkv

After:
Wolverine.And.The.X-Men.S01E01.Hindsight.(1).720p.x264-aaf.mkv

EDIT: Changed season+episode numbering as per suggestion from rednoah to inbuilt expression that handles special cases and multi-episodes.
g3rman
Donor
Posts: 18
Joined: 24 Oct 2013, 16:14

Re: How about sharing our format expressions?

Post by g3rman »

Here's what I came up with:

Code: Select all

filebot -rename -r "F:\Downloads" --db thetvdb -non-strict --format "F:\British TV\{folder.path.match(/Arts and Culture|Comedy|Documentary|Drama|Game Show|Horror|Kids|Motoring|Music|Mystery|Planes and Trains|Property|Radio|Reality|Sci-Fi|Soaps|Special Events|Talkshow|Travel/)}\{n.replaceAll(':|\\?',' -').replaceAll('(?i)\\s-\\s\\(uk\\)|(?i)\\s\\(uk\\)')}\Series {s}\{n.replaceAll(':|\\?',' -').replaceAll('(?i)\\s-\\s\\(uk\\)|(?i)\\s\\(uk\\)')} - {S00E00}"
Before:
F:\Downloads\Comedy\The Graham Norton Show s14e03.hannibal\The Graham Norton Show s14e03.hannibal.avi

After
F:\British TV\Comedy\The Graham Norton Show\Series 14\The Graham Norton Show - S14E03.avi

I have a set number of genres (comedy,documentary, etc) that I sort my shows by. I wanted to keep that list and not add genres as per TvDB.
With the help of rednoah I constructed the {folder.path.match} expression. I was initially matching on the the folder name two levels above the
avi file but sometimes the number of subfolders changed which required the use of folder.path.match.

Also certain shows will have a suffix of (UK). Since I'm only interested in UK shows anyways the expression will remove any (UK) from the filename.
Ambroisie
Supporter
Posts: 19
Joined: 06 Dec 2013, 22:08

Re: How about sharing our format expressions?

Post by Ambroisie »

The followings are my format exxpressions for TV series, movies and music (names maybe in french ;-) ) :
[It's a long post]
  • Series :
    Expression wrote:E:/Video/Séries/{n}/{"Saison ${s.pad(2)}"}/{n} - {s.pad(2)}x{e.pad(2)} - {t}
    Which creates :
    Output wrote:E:\Video\Séries\Firefly\Saison 01\Firefly - 01x01 - Serenity.avi
  • Films :
    Expression wrote:E:/Video/Films/{"$collection/"}{n} ({y}){ [{"${fn.match(/3D/)}, "}{"${cf}, "}{"${hpi}, "}{"${vc}, "}{"${ac}"}]}
    Which creates :
    Output wrote:E:\Video\Films\Avatar Collection\Avatar (2009) [3D, mkv, 720p, x264, ac3].mkv
  • Musics :
    Expression wrote:E:/Musique/{n}/{"$album/"}{"${album}."}{"${pi.pad(2)} - "} {t}
    Which creates :
    Output wrote:E:\Musique\Les Fatals Picards\Coming Out\Coming Out.02 - Dans mon verre.mp3
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

Re: How about sharing our format expressions?

Post by Ithiel »

Hi guys, I had a separate thread about this one, but figured I'd add the updated version to the sticky :-)

The three types are 'Movies', 'TV Shows', and 'Anime'.

-----------------------------------------------------------------------------------------------------------------------------

Movies:
Includes:
  • Organises movies based on 'collection',
    All names converted to Title Case (should re-capatalise Roman numerals though)
    List both Primary & Alternate Title (i.e. English & Japanese) if different
    Moves the 'The's to the end
    Replaces invalid characters from file, folder, and collection name
    Shows year and rating in the folder name
    Includes video resolution, video and audio codec, and audio channel info in the file name
    Retains tags for 3D, Extended, Uncut, Remastered, Uncut, Directors Cut, Unrated, Uncensored & Special Edition references
    Supports multi-part movies
Examples:
\\mynas\media\Movies\Twilight Saga, The\Twilight Saga - Eclipse, The (2010 PG-13)\Twilight Saga - Eclipse, The [720p x264 DTS 6ch].mkv
\\mynas\media\Movies\Rurôni Kenshin - Ishin Shishi E No Requiem (Samurai X - The Motion Picture) (1997 PG-15)\Rurôni Kenshin - Ishin Shishi E No Requiem [480p DivX MP3 2ch].avi
\\mynas\media\Movies\Alien Collection\Aliens (1986 R)\Aliens (Special Edition) Part 1 [360p XviD AC3 6ch].avi
\\mynas\media\Movies\Alien Collection\Aliens (1986 R)\Aliens (Special Edition) Part 2 [360p XviD AC3 6ch].avi
\\mynas\media\Movies\Sanctum 3D (2011 R)\Sanctum 3D [720p x264 AAC 6ch].mp4

Code: Select all

//mynas/media/Movies/{collection.replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/).replaceFirst(/^(?i)(Collection of the)\s(.+)/, /$2 Collection/).replaceAll(/Saga Collection/, "Saga").replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:|]/, " - ").replaceAll(/[?]/, "!").replaceAll(/[*\s]+/, " ")}\{norm = {it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:|]/, " - ").replaceAll(/[?]/, "!").replaceAll(/[*\s]+/, " ").replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }).replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/)}; norm(n)}{if (norm(n) != norm(primaryTitle)) ' ('+norm(primaryTitle)+')'}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""} ({y}{' '+any{certification}{imdb.certification}.replaceAll(/^\d+$/, 'PG-$0')})/{norm(n)}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""}{' (' + fn.matchAll(/extended|uncensored|remastered|unrated|uncut|directors.cut|special.edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[._]/, " ") + ')'}{" Part $pi"}{" [$vf $vc $ac $af]"}
-----------------------------------------------------------------------------------------------------------------------------

TV Shows:
Includes:
  • Season Based Folders & Episode Numbering
    All names converted to Title Case (should re-capatalise Roman numerals though)
    Includes full show name and episode title
    Replaces invalid characters from file and folder name
    Shows year and rating in the folder name, then organises episodes based on season or specials
    Includes video resolution, video and audio codec, and audio channel info in the file name
    Retains tags for 3D, Extended, Uncut, Remastered, Uncut, Directors Cut, Unrated, Uncensored & Special Edition references
Examples:
\\mynas\media\TV Shows\Pushing Daisies (2007 TV-PG)\Season 01\Pushing Daisies S01E01 Pie-Lette [360p XviD MP3 2ch].avi
\\mynas\media\TV Shows\Slap, The (2011 TV-MA)\Season 01\Slap, The S01E01 Hector [360p XviD MP3 2ch].avi
\\mynas\media\TV Shows\Straits, The (2012)\Season 01\Straits, The S01E01-E02 Proposition & The Trouble With Raskols, The [360p XviD MP3 2ch]
\\mynas\media\TV Shows\Looney Tunes (1930)\Season 1943\Looney Tunes S1943E01 Coal Black And De Sebben Dwarfs [240p MPEG MPEG Audio 2ch].mpeg

Code: Select all

//mynas/media/TV Shows/{norm = {it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:|]/, " - ").replaceAll(/[?]/, "!").replaceAll(/[*\s]+/, " ").replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }).replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/)}; norm(n)}{if (norm(n) != norm(primaryTitle)) ' ('+norm(primaryTitle)+')'}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""} ({y}{' '+any{certification}{imdb.certification}.replaceAll(/^\d+$/, 'PG-$0')})/{episode.special ? 'Special' : 'Season '+s.pad(2)}/{norm(n)} {episode.special ? 'S00E'+special.pad(2) : s00e00} {norm(t)}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""}{' (' + fn.matchAll(/extended|uncensored|remastered|unrated|uncut|directors.cut|special.edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[._]/, " ") + ')'}{" Part $pi"}{" [$vf $vc $ac $af]"}
-----------------------------------------------------------------------------------------------------------------------------

Anime:
Includes:
  • Absolute Episode Numbering (2 or 3 digits, auto calculating)
    All names converted to Title Case (should re-capatalise Roman numerals though)
    List both Primary & Alternate Title (i.e. English & Japanese) if different, and includes full episode title
    Moves the 'The's to the end
    Replaces invalid characters from file and folder name
    Shows year and rating in the folder name
    Includes video resolution, video and audio codec, and audio channel info in the file name
    Retains tags for 3D, Extended, Uncut, Remastered, Uncut, Directors Cut, Unrated, Uncensored & Special Edition references
Examples:
\\mynas\media\Anime\Blade Of The Immortal (Mugen No Juunin) (2008)\Blade Of The Immortal - 01 - Criminal [576p x264 AAC 2ch].mp4
\\mynas\media\Anime\Freezing (2011 N A)\Freezing - 01 - Untouchable Queen (Uncensored) [720p x264 AAC 2ch].mkv
\\mynas\media\Anime\One Piece (1999 TV-PG)\One Piece - 001 - I'm Luffy! The Man Who's Gonna Be King Of The Pirates! [480p XviD MP3 2ch].avi
\\mynas\media\Anime\Eternal Aseria, The [Eien No Aseria] (2005)\Eternal Aseria, The - 01 - Voice Of Motome [480p XviD MP3 2ch].avi

Code: Select all

//mynas/media/Anime/{norm = {it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:|]/, " - ").replaceAll(/[?]/, "!").replaceAll(/[*\s]+/, " ").replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }).replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/)}; norm(n)}{if (norm(n) != norm(primaryTitle)) ' ('+norm(primaryTitle)+')'}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""} ({y}{' '+any{certification}{imdb.certification}.replaceAll(/^\d+$/, 'PG-$0')})/{norm(n)} - {absolute.pad(episodelist.size() < 99 ? 2 : 3)}{'Special '+special.pad(episodelist.size() < 99 ? 2 : 3)} - {norm(t)}{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""}{' (' + fn.matchAll(/extended|uncensored|remastered|unrated|uncut|directors.cut|special.edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[._]/, " ") + ')'}{" Part $pi"}{" [$vf $vc $ac $af]"}
Note: The anime scheme is for anime series. While you can use it for anime movies, IMO you're best to use the movie format (assuming it's listed on IMDB, theMovieDB or OpenSubtitles).

-----------------------------------------------------------------------------------------------------------------------------

OP: http://www.filebot.net/forums/viewtopic.php?f=5&t=1205

Note: It kind of goes without saying, but be sure to replace '//mynas/media/' and what not with the path to wherever you're storing all your stuff.


MINIMUM VERSION REQUIREMENTS: You must have at least filebot-3.8-r1950 (released 2013/12/28) for the above to function properly. ^.^

Cheers,

~Ithiel

(Last Updated 2014/01/06)

UPDATE: Like this naming scheme? Check out this Advanced Windows Context Menu script for Windows that comes pre-configured with all this wizardry (and more cool stuff)
http://www.filebot.net/forums/viewtopic.php?f=3&t=1222
There can be only one Power² User
nothinghere
Posts: 8
Joined: 13 Jul 2014, 18:10

Re: How about sharing our format expressions?

Post by nothinghere »

The ones I am using. Major thanks to Ithiel and Rednoah for some of the parts.

Movies:

Code: Select all

{norm={it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/\u0022/, '\'').replaceAll(/[:|]/, '.').replaceAll(/\?/, '!').replaceAll(/[*\s\.,]+/, '.').replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/[0-9](th|nd|rd)/, { it.lower() })};isLatin = {java.text.Normalizer.normalize(it, java.text.Normalizer.Form.NFD).replaceAll(/\p{InCombiningDiacriticalMarks}+/, '') ==~ /^\p{InBasicLatin}+$/}; isLatin(info.OriginalName) ? norm(info.OriginalName) : norm(primaryTitle) }.({y}){if(isLatin(info.OriginalName) && info.OriginalName != primaryTitle && !(info.SpokenLanguages[0] ==~ /(sv|da|no)/)) '.'+ norm(primaryTitle) }{'.'+vf}{'.'+source}{fn.contains('3D') || fn.contains('3-D') ? '.3D':''}{'.'+fn.replace(/(?i)\.DC\./, '.directors.cut.').replaceAll(/director\'?s|theatrical|ultimate/,'$0.Cut').matchAll(/UNCENSORED|UNRATED|REMASTERED|EXTENDED|UNCUT|DIRECTOR\'?S.CUT|THEATRICAL.CUT|ULTIMATE.CUT|FINAL.CUT|SPECIAL.EDITION/)*.upperInitial()*.lowerTrail().sort().join('.')}{'.'+fn.matchAll(/PROPER|REPACK/)*.upper().sort().join('.')}{'.'+vc.replace('Microsoft', 'VC-1')}{'.'+ac.replace('MPEG Audio', 'MP3')}{audio.FormatProfile =~ /MA Core/ ? '-HD.MA' : ''}{audio.FormatProfile =~ /ES/ ? '-ES' : ''}{audio.FormatProfile =~ /Pro/ ? '-Pro' : ''}{'.'+af.replace('8 6ch', '7.1').replace('7 6ch', '6.1').replace('6ch', '5.1').replace('3ch', '2.1').replace('2ch','2.0').replace('1ch','1.0')}{def g = c{group}; def m = c{fn.match(/(?:(?<=[-])[a-z0-9]+$)|(?:^[a-z0-9]+(?=[-]))/)}; if(g==null && m!=null) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null && m!=null && m.lower()!=g.lower()) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null) return '-'+g;}
I am using the original title if it the alphabet used is latin based. If the original title is not the same as the english title, and the first spoken language is not Swedish, Norwegian or Danish I will add the English title as part of the filename. This way I can keep the original titles which I prefer, but still have a chance to find them/connect them to the English titles most commonly used when talking to people. The Nordic stuff is because I live there so I know which movies they are.
If you want to use the format but don't want the special hack for Nordic stuff remove the text: "&& !(info.SpokenLanguages[0] ==~ /(sv|da|no)/)"
The audio/movie codecs are hacked a bit to be named by their real/common names instead of the ones defined by mediainfo. I.e. DTS-HD MA, MP3, VC-1 instead of DTS MA Core, MPEG Audio and Microsoft respectively.

Examples:
Kôkaku.Kidôtai.2.0.(2008).Ghost.In.The.Shell.2.0.720p.REPACK.x264.DTS.5.1-timeshift.mkv // Latin characters but added english name
Jagten.(2012).1080p.BluRay.x264.DTS-HD.MA-GRYM.mkv // Original name only, primary language is Danish
My.Sassy.Girl.(2001).720p.BluRay.x264.AC3.5.1-EbP.mkv // Actual name is 엽기적인 그녀, or transliterated to Yeopgijeogin Geunyeo
I would have loved to figure out how to keep the transliterated names, but using {transliterate(info.OriginalTitle)}did not work perfectly, which meant a bunch of titles missed when doing searched.
For my sassy girl the transliteration was something like Yeobgi-jeogin Geunyeo or the like, which is really close, but far away to miss some lookups.

NOTE: I do not care for multipart files so I do not support them. I rip my movies as single files without any splits.



Series is a bit simpler as I only care about the name we get from TheTVDB (I have long since abandoned any hope that they'll change their mind and structure series as they were intended instead of simply how they where broadcasted):

Code: Select all

{n}/{episode.special ? 'Specials' : 'Season '+s}/{norm={it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/\u0022/, '\'').replaceAll(/[:|]/, '.').replaceAll(/\?/, '!').replaceAll(/[*\s\.]+/, '.').replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/[0-9](th|nd|rd)/, { it.lower() })};norm(n) }.{episode.special ? 'S00E'+special.pad(2) : s00e00}.{norm(t)}{'.'+vf}{'.'+source}{'.'+fn.matchAll(/PROPER|REPACK/)*.upper().sort().join('.')}{'.'+vc.replace('Microsoft', 'VC-1')}{'.'+ac.replace('MPEG Audio', 'MP3')}{audio.FormatProfile =~ /MA Core/ ? '-HD.MA' : ''}{audio.FormatProfile =~ /ES/ ? '-ES' : ''}{audio.FormatProfile =~ /Pro/ ? '-Pro' : ''}{'.'+af.replace('8 6ch', '7.1').replace('7 6ch', '6.1').replace('6ch', '5.1').replace('3ch', '2.1').replace('2ch','2.0').replace('1ch','1.0')}{def g = c{group}; def m = c{fn.match(/(?:(?<=[-])[a-z0-9]+$)|(?:^[a-z0-9]+(?=[-]))/)}; if(g==null && m!=null) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null && m!=null && m.lower()!=g.lower()) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null) return '-'+g;}
NOTE: I do not pad the season numbering (i.e. I use Season 1, Season 2 instead of Season 01, Season 02).
Specials end up in a /Specials folder instead. Same thing for video/audio as movies have.

Examples:
Coupling\Season 1\Coupling.S01E01.Flushed.360p.DVDRip.x264.AAC.mkv
Doctor Horrible's Sing-Along Blog\Season 1\Doctor.Horrible's.Sing-Along.Blog.S01E01.Act.I.1080p.BluRay.x264.DTS-DIMENSION.mkv


If anyone wants to copy my thing entirely the script I use to sort everything is:

Code: Select all

filebot -script fn:amc "x:/downloads" --log-file d:\amc-run.log --output "//nas/" --action move --conflict skip -non-strict --def clean=y --def "movieFormat=Movies/{norm={it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/\u0022/, '\'').replaceAll(/[:|]/, '.').replaceAll(/\?/, '!').replaceAll(/[*\s\.,]+/, '.').replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/[0-9](th|nd|rd)/, { it.lower() })};isLatin = {java.text.Normalizer.normalize(it, java.text.Normalizer.Form.NFD).replaceAll(/\p{InCombiningDiacriticalMarks}+/, '') ==~ /^\p{InBasicLatin}+$/}; isLatin(info.OriginalName) ? norm(info.OriginalName) : norm(primaryTitle) }.({y}){if(isLatin(info.OriginalName) && info.OriginalName != primaryTitle && !(info.SpokenLanguages[0] ==~ /(sv|da|no)/)) '.'+ norm(primaryTitle) }{'.'+vf}{'.'+source}{fn.contains('3D') || fn.contains('3-D') ? '.3D':''}{'.'+fn.replace(/(?i)\.DC\./, '.directors.cut.').replaceAll(/director\'?s|theatrical|ultimate/,'$0.Cut').matchAll(/UNCENSORED|UNRATED|REMASTERED|EXTENDED|UNCUT|DIRECTOR\'?S.CUT|THEATRICAL.CUT|ULTIMATE.CUT|FINAL.CUT|SPECIAL.EDITION/)*.upperInitial()*.lowerTrail().sort().join('.')}{'.'+fn.matchAll(/PROPER|REPACK/)*.upper().sort().join('.')}{'.'+vc.replace('Microsoft', 'VC-1')}{'.'+ac.replace('MPEG Audio', 'MP3')}{audio.FormatProfile =~ /MA Core/ ? '-HD.MA' : ''}{audio.FormatProfile =~ /ES/ ? '-ES' : ''}{audio.FormatProfile =~ /Pro/ ? '-Pro' : ''}{'.'+af.replace('8 6ch', '7.1').replace('7 6ch', '6.1').replace('6ch', '5.1').replace('3ch', '2.1').replace('2ch','2.0').replace('1ch','1.0')}{def g = c{group}; def m = c{fn.match(/(?:(?<=[-])[a-z0-9]+$)|(?:^[a-z0-9]+(?=[-]))/)}; if(g==null && m!=null) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null && m!=null && m.lower()!=g.lower()) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null) return '-'+g;}" --def "seriesFormat=TV Shows/{n}/{episode.special ? 'Specials' : 'Season '+s}/{norm={it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/\u0022/, '\'').replaceAll(/[:|]/, '.').replaceAll(/\?/, '!').replaceAll(/[*\s\.]+/, '.').replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/[0-9](th|nd|rd)/, { it.lower() })};norm(n) }.{episode.special ? 'S00E'+special.pad(2) : s00e00}.{norm(t)}{'.'+vf}{'.'+source}{'.'+fn.matchAll(/PROPER|REPACK/)*.upper().sort().join('.')}{'.'+vc.replace('Microsoft', 'VC-1')}{'.'+ac.replace('MPEG Audio', 'MP3')}{audio.FormatProfile =~ /MA Core/ ? '-HD.MA' : ''}{audio.FormatProfile =~ /ES/ ? '-ES' : ''}{audio.FormatProfile =~ /Pro/ ? '-Pro' : ''}{'.'+af.replace('8 6ch', '7.1').replace('7 6ch', '6.1').replace('6ch', '5.1').replace('3ch', '2.1').replace('2ch','2.0').replace('1ch','1.0')}{def g = c{group}; def m = c{fn.match(/(?:(?<=[-])[a-z0-9]+$)|(?:^[a-z0-9]+(?=[-]))/)}; if(g==null && m!=null) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null && m!=null && m.lower()!=g.lower()) return '-'+m.replace(/^tpz$/, 'TOPAZ'); if(g!=null) return '-'+g;}"
NOTE: Remember to update the paths to your series/movies and downloads.
Paste everything into a file called amc.cmd or something and double click it to run it.
DevXen
Power User
Posts: 164
Joined: 12 Oct 2014, 21:15

DevXen's Enhanced TV SHOW Perfection Naming Scheme

Post by DevXen »

DevXen's Enhanced TV SHOW Perfection Naming Scheme

---Last Updated: 10.25.2018---

Here is my naming scheme For TV Shows that I've worked on for the last couple weeks on. The goal was to make it as automated as possible by anticipating every scenario I could think of. If I have missed anything, or there are any bugs, or you found a better way to do any of this, then please let me know!

Code: Select all

{'H:/Live Action/[Naming]/'}{if (s3d) '3D/'}{model.episodes.flatten().containsAll(episodelist.findAll{it.season == s && it.episode && it.title}) ? '[Finished]/' : '[Current Seasons]/'}{if (episode.special) '[Finished]/'}{csv('C:/FileBot Settings/TV/TVGenreFolderBasedOnSeriesName.csv').get(n) ?: genre +'/'}{norm = {it.upperInitial().lowerTrail().replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/.web./, "web-dl").replaceAll(/[:|]/, " - ").replaceAll(/[?]/, "!").replaceAll(/[*\s]+/, " ").replaceAll(/\b[IiVvXx]+\b/, { it.upper()}).replaceAll(/\b[0-9](?i:th|nd|rd)\b/, {it.lower()})}; norm(n).replaceFirst(/^(?i)(The|A|An)\s(.+)/, /$2, $1/).replaceTrailingBrackets()}{' '+n.match(/\([A-Z]+\)$/)}{if (norm(n) != norm (primaryTitle)) ' ('+norm(primaryTitle)+')'}{s3d ? ' '+'3D':""}{if (y) {' ['+y +']'}}{' '+any{"[$certification]"}{"["+$imdb.certification+"]" }.replaceAll('N A','').replaceAll(/^ \d+$/, 'PG-$0')}{" [$rating" + "★]"} [{csv('C:/FileBot Settings/TV/TVNetwork.csv').get(info.network) ?: info.network }]/{[episodelist.findAll{ it.season == s }.airdate.year.min()]}{episode.special ? '[Specials]' : ' - Season '+s.pad(2)}{' '}{' (' + file.path.matchAll(/extended|uncensored|remastered|unrated|uncut|unedited|directors.cut|special.edition|unsold.pilot|broadcast.version|alternate.ending|with.original.commercials|reconstructed|with.commercials|unaired.pilot|unaired.episode/).unique()*.upperInitial()*.lowerTrail().sort().join(') (').replaceAll(/ [._]/, " ") +') '}{episode.special ? '': {def sources = model.findAll{ it.n == n && it.s == s }.source.minus(null).unique(); sources.size() >= 1 ? sources.size() == 1 ? sources : '[Mixed]' : (fn.upper() =~ /.WEB.|WEBDL|WEB.DL/ ? /[WEB-DL]/ : '[No Source]')}}{model.episodes.flatten().containsAll(episodelist.findAll{it.season == s && it.episode && it.title}) ? '' : ' [Incomplete]'}/{csv('C:/FileBot Settings/TV/TVFileShowNames.csv').get(n) ?: norm(n).replaceTrailingBrackets()}{' '+n.match(/\([A-Z]+\)$/)}{' '+n.match(/\([0-9]+\)$/)} {'- '+S00E00+' -'} {norm(t.replaceAll("\\s*[(]([^)]*)[)]\$", { group, match -> ' (Part '+match.pad(2)+')' }))}{if (episode.special) ' [Special]'}{s3d ? ' '+'3D':""}{' (' + file.path.matchAll(/extended|uncensored|remastered|unrated|uncut|unedited|directors.cut|special.edition|unsold.pilot|broadcast.version|alternate.ending|with.original.commercials|reconstructed|with.commercials|unaired.pilot|unaired.episode/).unique()*.upperInitial()*.lowerTrail().sort().join(') (').replaceAll(/ [._]/, " ") + ')'}{" Part $pi"}{" [$minutes Min]"}{airdate.format(" [MM.dd.yyyy]")}{fn.upper() =~ /.WEB.|WEBDL|WEB.DL/ ? / [WEB-DL]/ :" ["+any{source}{'No Source'}+"]"}{" [$vf $ac $af]"}
I'm not sure if I can remember all I've done to it. it is based on: "Ithiel's super crazy renaming scheme for perfectionists!" I just decided to perfect it for my needs.

Changes/Updates/Additions
  • 1. More Accurately matches Complete/Incomplete seasons as it looks for The Episode title as well as season. Removing Specials and Numbered but unlisted episodes from matching.
    2. I Put the Country Code back in the Folder name and capitalized it. i.e.: "(US)" when it's part of the show name on TheTVDB To Differentiate between Shows like: Wilfred and Wilfred (US), Being Human and Being Human (US), Etc
    3. Added the Year the show started To the folder (To differentiate between tv show remakes: Knight Rider [1982] vs. Knight Rider [2008]
    4. When the year is included in TheTVDB Show name then I added it to the filename as well. (2008)
    5. Moved 'The', 'A', and 'An' to the end of the TV Show name on the folder, but not on the show or episode names on the file. (Every Big Bang Theory episode name starts with 'The'.)
    6. I put the Episode Parts back in and Padded it as well. (Part 01), (Part 02), etc. (Edit: This is working again)
    7. Added: [TV Rating] [Star Rating] [Network] to the Folder show name. [TV-PG] [9.5★] [FOX]
    8. Added the Year the season started to the Season folder [2008] - Season 01, [2009] - Season 02, etc.
    9. Added: [Actual Minutes of the Episode] [Original Airdate] [Source] [Resolution Standard Audio Codec Audio Channels] To the File name. [21 Min] [03.05.2011] [DVDRip] [360p AAC 2ch]
    10. Added a CSV File for Matching: TVNetwork.csv as Some networks are longer than needed: National Geographic;NeoGeo .. The CW;CW .. etc.
    11. Added a CSV file for Matching: TVFileShowNames.csv as some show names are a bit long, when it's already in the folder name, So: Epic Rap Battles of History;ERB .. How it Should have Ended;HISHE
    12. Moved the specials to the season to which their aired under a [Specials] Sub Folder
    13. added: unsold.pilot, unaired.pilot, unaired.episode To the Extended info matching check.

    ---Updated: 10.28.2014---
    14. Added genre folder name CSV File check based on series name (I.E.: Being Human (US) now goes to Horror instead of Comedy.)

    ---Updated: 10.13.2018---
    15. Removed Redundant Folders for Finished/Naming separation for better code.
    16. Changed From manual padding to S00E00 For better code.
    17. Changed from Manual to 3D Binding for better code.
    18. Now sorts 3D files into a separate /3D/ folder and adds 3D to the filename.
    19. Fixed Specials so now they go to the correct path and not the root of the drive.
    20. Fixed Double Episodes to sort into finished folder when the season is complete.
    21. Stopped Additional info from being added more than once if it's found in Filename and/or folder (I.E. Unrated, Extended)
    22.
    • Added [Source] To the Season folder. (Ex: [DVDRip])
      A. If Season episodes contains different sources. it adds [Mixed] To the Season folder.
      B. if Episodes have no source. it adds [No Source] to season folder.
    ---Updated: 10.14.2018---
    23. Added [Incomplete] to the season folder if there are missing episodes in that season.

    ---Updated: 10.25.2018---
    24. Fixed the .web./webdl/web.dl/etc in filename issue of not finding it as a source and corrected it in the season folder and filename
    25. moved [Incomplete] to be added after the [Source] in the season folder name.
    26. Added GitHub links to scripts.

Filename Examples:
  • Action\Leverage [2008] [TV-14] [8.5★] [TNT] [DVDRip]\[2008] - Season 01 (DVDRip)\Leverage - S01E05 - The Bank Shot Job [43 Min] [12.30.2008] [DVDRip] [360p MP3 2ch].avi

    Action\Viper (Full) [1994] [8.1★] [NBC] [DVDRip]\[1997] - Season 03 (DVDRip)\Viper - S03E01 - Triple Cross [43 Min] [09.23.1997] [DVDRip] [480p MP3 2ch].avi

    Horror\American Horror Story [2011] [TV-MA] [8.5★] [FX] [DVDRip]\[2012] - Season 02 (DVDRip)\American Horror Story - S02E06 - The Origins Of Monstrosity [41 Min] [11.21.2012] [DVDRip] [480p AAC 2ch].mkv

    Comedy\Inside Amy Schumer [2013] [TV-MA] [7.4★] [Comedy Central] [HDTV & WEB-DL]\[2013] - Season 01 (HDTV)\Inside Amy Schumer - S01E04 - The Horror [21 Min] [05.21.2013] [HDTV] [480p AAC 2ch].mp4

    Web Shows\Cyanide & Happiness Show, The [2010] [10.0 Stars] [YouTube]\[2010] - Season 01\The Cyanide & Happiness Show - S01E01 - The Sign [0 Min] [02.01.2010] [WEB-DL] [720p AAC 2ch].mp4

    Web Shows\How It Should Have Ended [2007] [YouTube]\[2007] - Season 01\HISHE - S01E01 - How The Matrix Should Have Ended [1 Min] [03.06.2007] [WEB-DL] [360p AAC 2ch].mp4

Like i said I could be missing things I've done. But Assuming that I'm not. Everything else should still be the same as: "Ithiel's super crazy renaming scheme for perfectionists!". You can find his naming scheme at: http://www.filebot.net/forums/viewtopic.php?f=5&t=1205

The CSV files I am using
  • C:\FileBot Settings\TV\TVGenreFolderBasedOnSeriesName.csv
    C:\FileBot Settings\TV\TVFileShowNames.csv
    C:\FileBot Settings\TV\TVFolderShowNames.csv
    C:\FileBot Settings\TV\TVNetwork.csv
(These are all in: What To Match;What You want to replace it with Format)

If there is a better, faster, more efficient, Smaller way to do Anything in my naming scheme, Please share.

Also there are a couple other things I'd like to do to it. but Haven't been able too, so if any of you out there, want to tackle these ideas, That'd be rad. and if not, it's pretty good as it is.

The things i would still like to add are:
  • 1. A csv filecheck for the Foldername. So you can match shows like: Avatar The last Air bender, and the Legend of Kora in the same folder, under different sub folders. (As explained in the post in this thread, by: SyAccursed) - I worked on it for a few hours, but was unable to get it to work correctly.
    2. A way to check if the show has ended. and if you have every episode of every season put (Full) in the show folder name.
    3.Check the sources of each episode in the folder if they all are the same add (Source) to the Season Folder name. If they are not the same add (Mixed) or each source in the season (HDTV & DVDRip) [I haven't decided which I like better yet.] - To the season folder name.
    4. And also, find a way to check to see if the show is in the middle of airing the current season, if so. put those files in a (Currently airing) folder as they won't be complete until the season ends. - so it'd be a 3 way split. 1. Completed Seasons. 2. Incomplete Season. 3. Currently airing Seasons. (The idea being to identify the incomplete seasons to complete them. and not to move the currently airing seasons to the main folder until the season is over.
These Ideas I haven't been able to get working yet. But they would make the naming scheme perfect for me. So if I can get them working, i'll update this post accordingly. If anyone else out there, would like to give them a try, that'd be cool too. and as i said, if not. it's usable and nearly complete as it is, so Enjoy.

I'd also like to thank rednoah, for all his help with several issues i've had working this out. and putting up with my crazy annoying requests for help. haha. I'd also like to thank everyone else that has posted ideas, and things that work, and better ways to do things, that i was able to pick up here in the forums. without that, and those examples, I don't think I could have figured out how to do any of it. so If I used an idea of yours and didn't credit you, I apologize. Let me know And I will.

I've added my scripts to GitHub. along with my CSV Files:

GitHub: https://github.com/DevXen/MediaNamingScripts

TV Shows: https://raw.githubusercontent.com/DevXe ... _Shows.txt
Last edited by DevXen on 25 Oct 2018, 16:11, edited 10 times in total.
DevXen
Power User
Posts: 164
Joined: 12 Oct 2014, 21:15

DevXen's Enhanced MOVIE Perfection Naming Scheme

Post by DevXen »

DevXen's Enhanced MOVIE Perfection Naming Scheme

Here is my naming scheme For Movies, I've worked on for the last couple weeks on. The goal was to make it as automated as possible by anticipating every scenario I could think of. If I have missed anything, or you find any bugs, or you come up with a better way to do any of this, then please let me know!

Code: Select all

{any{if (file.path.lower().matchAll(/(3d|half|full|h?sbs|f?sbs|(?i)(?<=^|[^a-z])hou(?=$|[^a-z])|(?i)(?<=^|[^a-z])fou(?=$|[^a-z])|f.ou|anaglyth)(?:.sbs|(?i)(?<=^|[^a-z])cat(?=$|[^a-z]))?/)){'C:/[3D Movies]/'}}{'C:/Movies/'}}{any{def map=['erinbrown':'[Actors]/Erin Brown','stephenking':'[Stephen King]']; actors.join(', ').lower().replaceAll(/[\W]/, "").matchAll(/erinbrown|stephenking/).findResults{ map[it] }.join(',')+'/'}{def map=[/rifftrax/:'RiffTrax','miniseries':'Mini-Series','monstervision':'MonsterVision','fanedit':'FanEdits','usaupallnight':'USA Up All Night',/elvirasmoviemacabre/:'Elvira\'s Movie Macabre']; '['+file.path.lower().replaceAll(/[\W]/, "").matchAll(/monstervision|rifftrax|fanedit|usaupallnight|elvirasmoviemacabre/).findResults{ map[it].replaceAll("\\[|\\]", "") }.sort{ map.values().indexOf(it)}.join(',')+']/'}{(info.SpokenLanguages.displayLanguage.contains(/English/)) ? '' : '[Foreign Films]/'}}{any{if (genres.join(',  ').matchAll(/^(?=.*drama)(?=.*history|biography)/))('Docudrama')}{if (genres.join(',  ').matchAll(/animation/))('Animation/')}{any{if (genres.join(',  ').matchAll(/musical/))('Musicials/')}{if (omdb.genres.join(',  ').matchAll(/musical/))('Musicials/')}}{(csv('C:/FileBot Settings/Movies/MovieGenres.csv').get(n))}{genre}{'[No Genre]'}}/{norm =  {it.upperInitial().lowerTrail().replaceTrailingBrackets().replaceAll(/[`´‘’ʻ""“”]/, "'").replaceAll(/[:|]/, " -  ").replaceAll(/[?]/, "!").replaceAll(/[*\s]+/, " ").replaceAll(/\b[IiVvXx]+\b/, { it.upper() }).replaceAll(/\b[0-9](?i:th| nd|rd)\b/, { it.lower() }).replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/)}; norm(n)}{if (norm(n) != norm(primaryTitle)) '  ('+norm(primaryTitle)+')'}{" (Part ${pi.pad(2)})"}{" ["+file.path.lower().replace(/dc/, 'director\'s cut').replaceAll('limited','limited release').replaceAll('directors','director\'s').replaceAll('-','').replaceAll(/director.s|theatrical/,'$0 Cut').matchAll(/(uncensored|uncut|unrated|remastered|ultimate|extended|director?s|theatrical|ultimate|final|bootleg|special|fan?edit?|limited|rifftrax|monstervision|youtube|hulu|netflix|vimeo|edited|edit|censored+)(?:.edition|.cut|.version|.edit|.release|.extended|.rip)?/)*.upperInitial()*.lowerTrail().sort().join('] [')+']'}{def map=['3d':'3D','hsbs':'Half-SBS','halfsbs':'Half-SBS','fsbs':'Full-SBS','fullsbs':'Full-SBS','sbs':'SBS','halfou':'Half-OU','fullou':'Full-OU','overunder':'OU','anaglyth':'Anaglyth']; " ("+ ((file.path.lower().contains(/3d/)) ? '' : '3D ')+ file.path.lower().replaceAll(/(?i)(?<=^|[^a-z])hou(?=$|[^a-z])/,'halfou').replaceAll(/(?i)(?<=^|[^a-z])fou(?=$|[^a-z])/,'fullou').replaceAll(/(?i)(?<=^|[^a-z])ou(?=$|[^a-z])/,'overunder').replaceAll(/[\W]/, "").matchAll(/3d(?!.*?3d)|hsbs(?!.*?hsbs)|halfsbs(?!.*?halfsbs)|fsbs(?!.*?fsbs)|fullsbs(?!.*?fullsbs)|sbs(?!.*?sbs)|halfou(?!.*?halfou)|fullou(?!.*?fullou)|overunder(?!.*?overunder)|anaglyth(?!.*?anaglyth)/).findResults{ map[it]}.sort().join(' ')+')'}{any{" ["+d.format("yyyy")+"]"}{y}}{info.SpokenLanguages.displayLanguage.contains(/English/) ? '' : " ["+any{(audios.language[1]) ? (csv('C:/FileBot Settings/All/Locales.csv').get(audios.language[0]))+", "+(csv('C:/FileBot Settings/All/Locales.csv').get(audios.language[1])) : (csv('C:/FileBot Settings/All/Locales.csv').get(audios.language[0]))}{(info.SpokenLanguages.displayLanguage.join(', '))}+"]"}{' ['+any{certification} {omdb.certification}.replaceAll(/^\d+$/, 'PG-$0').replaceAll('N A','No Certification')+']'}{" [$minutes Min]"}{" ["+(rating)+"★]"}{" ["+any{(csv('C:/FileBot Settings/Movies/MovieSource.csv').get(source))}{(source)}{'No Source'}+"]"}{" [$vf] [$ac "+af.replace('8ch', '7.1ch').replace('7ch', '6.1ch').replace('6ch', '5.1ch').replace('3ch', '2.1ch').replace('2ch','2.0ch')+"]"}{" ("+actors.take(3).join(', ')+")"}{any{" ("+omdb.genres.take(3).join(', ')+")"}{" ("+genres.take(3).join(', ')+")"}}

I'm not sure if I can remember everything i've done. but here's a try. like the TV Show script i did above. this is also based on: "Ithiel's super crazy renaming scheme for perfectionists!" I have added to it and changed it for my own needs.

Changes/Additions:
  • 1. Special Movies Organization
    • 1.1: If the file or path indicates it's a 3D movie it is put in the "[3D Movies]" folder, if not then it'll be put it in the "Movies" folder
      1.2: If the list of Actors for the movie include 'Erin Brown' Then the movie is put in: "[Actors]/Erin Brown" folder
      1.3: All 'Stephen King' movies are put in the "[Stephen King]" Folder.
      1.4: If the file or path indicate special movies, they are organized separately (RiffTrax, MonsterVision, Mini-Series, Elvira's Movie Macabre, etc.)
      1.5: If the movie is not in 'English' it is put in the "[Foreign Films]" Folder.
    2. Genres
    • 2.1: If movie genre list contains "Drama" & "History", or "Drama" & "Documentary", then it is put in the 'Docudrama' folder.
      2.2: If movie genre list contains "Animation" then it is put in the 'animation' folder. (Live Action/Animation Mix also goes to Animation.)
      2.3: If The Movie genre list contains "Musical" it is put in the 'Musicals' Folder.
      2.4: Checks Movie title in "MoviesGenres.csv" if it's found it forces movie into the genre listed. (Both X Files movies both now go to "Drama")
      2.5: If none of the following happen, then it puts the movie in the primary genre folder. if there is no genre, it puts it in the '[No Genre]' folder.
    3. Ithiel's stuff.
    • 3.1: Correctly organize into movie collections. (Removed for the time being due to file length issues - May use a CSV file to force Collections)
      3.2: Remove Invalid Characters from movie titles.
      3.3: Correct Roman Numeral Casing
      3.4: correct 'nd', 'rd', 'th' on numbers as needed.
      3.5: Move 'The' to the end of the title.
      3.6: Add (Part ##) to multi movie parts/Mini-Series/etc.
    4. Alternate Movie Identification/Additional Movie Info
    • 4.1: Changes 'DC' to "(Director's Cut)".
      4.2: adds 'Cut' after "Theatrical" or "director's". (Director's Cut | Theatrical Cut)
      4.3: Adds any Additional movie types (Uncensored Edition, Ultimate Edit, Remastered Version, Limited Release, etc.)
      4.4: Identify if the movie is a 3D movie based on File and path. as well as what type of 3D and marks it accordingly. (3D Half-SBS), (3D Anaglyth), Etc
      4.5: Shows Year To The Movie: (2015)
      4.6: Shows Spoken Language, if not English: (Finnish), (German), (French), Spanish), Etc.
      4.7: Movie Certification Rating: [PG-13], [R], [G], Etc
      4.8: Added: [Actual Minutes of the Movie]
      4.9: Added: movie [Source], also checks against: MovieSource.csv to force the correct casing [DVDRip] vs. [DvDRiP]
      4.10: added [Resolution] [Audio Codec Audio channels] *Audio channels remapped to 2 digit format*: [1080p] [AAC 5.1ch]
      4.11: Added Top 3 Actors (Christopher Lambert, Robin Shou, Linden Ashby)
      4.12: Added Top 3 Genres: (Action, Adventure, Fantasy)
    *Note: Most of these are Modular/sequential, meaning they are split and move in the following order.
    For example: a 3d foreign film will go into the: "[3D Films]/[Foreign Films]/[Genre]" Folder.

Updates/Edits:
  • 1. 02.07.2015 - 3D Bug: Fixed 3D identification bug when folder, and file has 3D identification tags, They would be displayed for each time they were found in the path. (3D 3D Half-SBS 3D Half-SBS). Now it only shows them once as it should. (3D Half-SBS)

    2. 02.07.2015 - Language Bug: Fixed issue when audios.language pulled up 2 languages, causing the csv file check to return Null instead of fail.

Filename Examples:
  • [3D Movies]\Action\Captain America - The First Avenger (3D Half-SBS) [2011] [PG-13] [2 Min] [6.3★] [BDRip] [1080p] [AAC 2.0ch] (Chris Evans, Hugo Weaving, Tommy Lee Jones) (Action, Adventure, Sci-Fi).mp4

    Movies\[FanEdits]\Drama\Newsies [Edit] [1992] [PG] [2 Min] [5.6★] [No Source] [1080p] [AAC 2.0ch] (Christian Bale, Bill Pullman, Ann-Margret) (Drama, Musical).mp4

    Movies\Action\Captain America - The First Avenger [Director's Cut] [Limited Release] [2011] [PG-13] [2 Min] [6.3★] [DVDRip] [1080p] [AAC 2.0ch] (Chris Evans, Hugo Weaving, Tommy Lee Jones) (Action, Adventure, Sci-Fi).mp4

    Movies\Action\Lost Room, The (Part 01) [2006] [No Certification] [2 Min] [6.8★] [HDTV] [1080p] [AAC 2.0ch] (Peter Krause, Julianna Margulies, Kevin Pollak) (Action, Fantasy, Mystery).mp4

    Movies\Action\Lost Room, The (Part 02) [2006] [No Certification] [2 Min] [6.8★] [HDTV] [1080p] [AAC 2.0ch] (Peter Krause, Julianna Margulies, Kevin Pollak) (Action, Fantasy, Mystery).mp4

    Movies\Action\Mortal Kombat [Director's Cut] [Extended Edition] [1995] [PG-13] [2 Min] [5.8★] [No Source] [1080p] [AAC 2.0ch] (Christopher Lambert, Robin Shou, Linden Ashby) (Action, Adventure, Fantasy).mp4

    Movies\Docudrama\House Of Saddam [2008] [TV-MA] [2 Min] [3.8★] [VHSRip] [1080p] [AAC 2.0ch] (Yigal Naor, Shohreh Aghdashloo, Makram Khoury) (Biography, Drama, History).mp4
I think that covered all I've done, but I could be missing things However assuming that I'm not. Everything else should still be the same as: "Ithiel's super crazy renaming scheme for perfectionists!". You can find his naming scheme at: http://www.filebot.net/forums/viewtopic.php?f=5&t=1205

The CSV files I am using
  • C:\FileBot Settings\All\Locales.csv (for the backup langauge detection.)
    C:\FileBot Settings\Movies\MovieGenres.csv (To Force Genres Based on Movie Name)
    C:\FileBot Settings\Movies\MovieSource.csv (To Correct Casing in the movie source)
    (These are all in: What To Match;What You want to replace it with Format) i.e.: The X Files;Drama
If there is a better, faster, more efficient, Smaller way to do Anything in my naming scheme, Please share.

Also there are a couple other things I'd like to do to it. but Haven't been able too, so if any of you out there, want to tackle these ideas, That would be rad. and if not, it's pretty good as it is.

The things i would still like to add are:
  • 1. Proper movie collection naming that lists the movie number in the series (Matrix 1, Matrix 2 - Reloaded, Matrix 3 - Revolution, Etc)
    2. Check to see if I have the movie in both 2D and 3D.
    3. Check to see if I own the movie on DVD/Blu-Ray
    4. A way to organize Disney movies into their own folder.
    5. A Way to check multiple items against a CSV File (The actors list array for matches, for example). so I can streamline and get rid of all the Mappings above.
    6. A Way to search multiple genres together in a CSV file (so I can easily add Docudrama (Drama And Histroy, or Drama And Biography), or Dramedy, etc)
    7. Put Movie Collections back!
[/list]

These Ideas I haven't been able to get working yet. But they would make the naming scheme perfect for me. So if I can get them working, i'll update this post accordingly. If anyone else out there, would like to give them a try, that would be cool too. and as i said, if not. it's usable and nearly complete as it is, so Enjoy.

I'd also like to thank rednoah, his help once again with several issues i've had working this out. and putting up with my crazy annoying requests for help. haha. I'd also like to thank DavidRTurner for his advice and suggestions, as well as everyone else that has posted ideas, and things that work, and better ways to do things, that i was able to pick up here in the forums. without that, and those examples, I don't think I could have figured out how to do any of it. so If I used an idea of yours and didn't credit you, I apologize. Let me know And I will.


One last thing...

I don't plan on making a music naming/organizing script, as I already have one I made in Picard by Musicbrainz that does things I don't think FileBot has the ability to do. and as I spent several months on it. it's incredibly complex. But if you would like that script, just let me know, and i'll give it to you. or even post it if there are enough people interested (and rednoah is okay with it, of course. haha).
bumblebeeman
Posts: 3
Joined: 11 Mar 2015, 12:59

Re: How about sharing our format expressions?

Post by bumblebeeman »

Hi!

I have a short script for use with with the GUI.

Code: Select all

F:/Filme{fn =~ /3D/ ? ' 3D' : ''}{fn =~ /3d/ ? ' 3D' : ''}/{collection+'/'}{n} ({y}) {genres}/{n} ({y}) ({vf}) ({af}){fn =~ /3dhsbs/ ? '.3D.H-SBS' : ''}{fn =~ /H-SBS/ ? '.3D.H-SBS' : ''}{fn =~ /3dhou/ ? '.3D.H-OU' : ''}{fn =~ /H-OU/ ? '.3D.H-OU' : ''}{' - CD'+pi}
It sorts 3D Movies in a seperate folder and names them with H-SBS or H-OU.
stephen147
Donor
Posts: 131
Joined: 01 Sep 2015, 22:40

Re: How about sharing our format expressions?

Post by stephen147 »

:!: ANY BUGS PLEASE LET ME KNOW BY PRIVATE MAIL :!:
:!: USE AT YOUR OWN PERIL :!:

TV Shows:
Will move files organised to folders: DRIVELETTER:\TV\Californication\Californication - (2014-04-20) S07E02 - Julia 480p HDTV AAC 2ch x264_mSD
  • Load in your eposide files & subtitle files into Filebot. (You can also do this by dragging the folders of those into Filter in Filebot and and CTRL+Selecting the folders on the right (Video & Subtitle) and dragging them folders into the Rename on the righthand side.
  • Then in settings > check 'override the extension'. which will rename both movie and subs all in one go when to click rename.

Code: Select all

G:\TV\{n.replace(':','-').replaceAll(/[\/:*?"<>|]/,' - ')}/{n.replace(':','-').replaceAll(/[\/:*?"<>|]/,' - ')}
({any{self.d}{'0000-00-00'}})
[{info.network}]
{episode.special ? 'S00E'+special.pad(2) : s00e00}
{t.after(/^[.]+/).replace(':','-').replaceAll(/[\/:*?"<>|]/,' - ')}
{self.vf ? self.vf + "" : self.hpi}
{"${self.source ?: 'NA'}"}
{ac}
{audio[0].channels.replaceAll(/2/, "2ch").replaceAll(/6/, "5.1ch")}    {vc}_{any{"$group"}{fn.match(/(?<=[_-])[^\s_-]+?$/)}{'NA'}.replaceAll(/[-_\[\]]\s*|\.\w{3}$/, "")}{any{'.'+lang}{lang}}{any{fn.match(/(?i)sdh.+?/)('')}{fn.match(/(?i).*sdh.*/)('_SDH')}}{any{fn.match(/(?i)\(foreignpartsonly\)/)}{''}}{"."+ext}
Will Return:
  • G:\TV\Californication\Californication - (2014-04-20) S07E02 - Julia 480p HDTV AAC 2ch x264_mSD.mkv
    G:\TV\Californication\Californication - (2014-04-20) S07E02 - Julia 480p HDTV AAC 2ch x264_mSD.eng.srt

OR
  • G:\TV\Californication\Californication - (2014-04-20) S07E02 - Julia 480p HDTV AAC 2ch x264_NA.mkv
    G:\TV\Californication\Californication - (2014-04-20) S07E02 - Julia 480p HDTV AAC 2ch x264_NA.spa.ssa


Notes about this code:

  • As you can see it truncates the language to 3 letters resulting in [eng, spa] etc.

    Deals with names in files like and retains them (this cannot be gotten by parsing the websites alone) and formats like so:
  • eng.foreignpartsonly.srt
  • eng.SDH.srt (SDH = Subtitles for the deaf or hard-of-hearing)


--============================================================

Folders, Movies & srt|sub|sbv|idx|ssa|ass|stl files.
Combines renaming of movie files folders, movie files themselves and movie subtitle files all in one go.

  • Load in your movie files & subtitle files into Filebot. (You can also do this by dragging the folders of those into Filter in Filebot and and CTRL+Selecting the folders on the right (Video & Subtitle) and dragging them folders into the Rename on the right-hand side.
  • Then in settings > check 'override the extension'. which will rename both movie and subs all in one go when to click rename.


Things to do & check before:

  • IMPORTANT: Ensure Movie file is in it's own folder to start with.

    For FIlebot to get the language of the sub file automatically they have to be named like so initially:
  • Filename.sublanguage.ext --> Real example: Captain Phillips (2013).english.srt
  • If the group is not found then _NA is appended to create continuity in the names.
  • If filebot cannot recognise the group then it gets the text from the end of the old filename to either the first gotten - or _
    e.g. 24 Hour Party People (2002)_mydvdrip will result in the new filename getting _mydvdrip appended to it.

Code: Select all

{
	def space = call{' '};
	// Root Directory
	def dir_root = 'Z:/Movies & TV/'+
	call{hd.matches(/(?i)SD/) ? '480p-720p/' : ' '}+
	call{hd.matches(/(?i)HD/) ? '720p-1080p/' : ' '}+
	call{hd.matches(/(?i)UHD/) ? '4k/' : ' '};
	// Main Title e.g.
	// 1408 (2007) (Director's Cut) 1080p HD Blu-ray non-HDR x264 DTS5.1ch_SiNNERS
	// 300 (2007) 720p HD BRRip non-HDR x265 DTS 5.1ch_ESiR
	// Deadpool (2016) 2160p UHD WEB-DL non-HDR AVC DTS-HD MA 7.1ch_DDR
	// Deadpool 2 (2018) (Super Duper Cut) 2160p UHD Blu-ray REMUX HDR10bit ATEME TrueHD Atmos 13Obj 7.1ch_EPSiLON
	def main_title = call{n}+
	space + '(' + call{y} + ')'+
	space + call{fn.matches(/(?i).+\b25th.+?anniv.+/) ? '(25th Anniv. Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\b\(limited\b.*?\).+/) ? '(Limited Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\b\(uncut\b.*?\).+/) ? '(Uncut)' : ' '}+
	space + call{fn.matches(/(?i).+\bcollector.+?s.+?edition\b.+/) ? '(Collector\'s Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\bdirect.+?cut\b.+/) ? '(Director\'s Cut)' : ' '}+
	space + call{fn.matches(/(?i).+\bextended.+?\b.+/) ? '(Extended)' : ' '}+
	space + call{fn.matches(/(?i).+\bextended.+?edit\b.+/) ? '(Extended Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\bimax\b.+/) ? '(IMAX Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\blimited\b.+/) ? '(Limited)' : ' '}+
	space + call{fn.matches(/(?i).+\bremastered\b.+/) ? '(Remastered)' : ' '}+
	space + call{fn.matches(/(?i).+\bsuper.+duper.+cut\b.+/) ? '(Super Duper Cut)' : ' '}+
	space + call{fn.matches(/(?i).+\btheatrical\b.+/) ? '(Theatrical)' : ' '}+
	space + call{fn.matches(/(?i).+\bunrated\b.+/) ? '(Unrated)' : ' '}+
	space + call{any{fn.match(/\([^\()+?[^\d]+?\)\s*/)} {' '}{' '}}+
	space + call{self.vf ? self.vf : self.hpi}+
	space + call{hd}+
	space + call{source.matches(/(?i)blu.*ray/) ? 'Blu-ray' : {source} ?: 'WEB-DL'}+
	space + call{fn.matches(/(?i).+\bremux\b.+/) ? 'REMUX' : ' '}+
	space + call{self.hdr ? self.hdr + bitdepth + 'bit' : 'non-HDR'}+
	space + call{vc}+
	space +
	// Call audio
	// Thread here where I got the base code: https://www.filebot.net/forums/viewtopic.php?f=5&t=5285
	call {
		def mCFP =
		[
		'AAC LC SBR' : 'AAC',
		'AAC LC' : 'AAC',
		'AC 3 Dep' : 'E-AC3',
		'AC 3' : 'AC3',
		'DTS 96 24' : 'DTS 96-24',
		'DTS ES XBR' : 'DTS-HD HRA',
		'DTS ES XLL' : 'DTS-HD MA',
		'DTS ES XXCH XBR' : 'DTS-HD HRA',
		'DTS ES XXCH XLL' : 'DTS-HD MA',
		'DTS ES XXCH' : 'DTS-ES',
		'DTS ES' : 'DTS-ES',
		'DTS XBR' : 'DTS-HD HRA',
		'DTS XLL X' : 'DTS X',
		'DTS XLL' : 'DTS-HD MA',
		'DTS' : 'DTS',
		'E AC 3 JOC' : 'EAC3 Atmos',
		'E AC 3' : 'EAC3',
		'MLP FBA 16 ch' : 'TrueHD Atmos',
		'MLP FBA' : 'TrueHD',
		'MP3' : 'MP3',
		'PCM' : 'PCM'
		];
		def audioClean = { it.replaceAll(/[\p{Pd}\p{Space}]/, ' ').replaceAll(/\p{Space}{2,}/, ' ').slash(' ') };
		def channelClean = { it.replaceAll(/Debug.+|Object\sBased\s?\/?|(\d+)?\sobjects\s\/\s|0.(?=\d.\d)|20/).replaceAll(/6/,'5.1').replaceAll(/8/,'7.1') };
		def audioCollection = audio.collect
		{ au ->
			def channels = any{ channelClean(au['ChannelPositionsString2'])}{ channelClean(au['ChannelsOriginal'])}{ channelClean(au['Channels']) };
			def dynChannel = {au['NumberOfDynamicObjects'] + 'Obj'};
			def ch = channels.tokenize('\\/').take(3)*.toDouble().inject(0, { a, b -> a + b }).findAll { it > 0 }.max().toString() + 'ch';
			def codec = audioClean(any{ au['CodecID/Hint'] }{ au['Format'] });
			def format_profile = { ( au['Format_AdditionalFeatures'] != null) ? audioClean(au['Format_AdditionalFeatures']) : '' };
			def combined = allOf{codec}{format_profile}.join(' ');
			def stream = allOf { mCFP.get(combined, 'UNKNOWN_FORMAT--'+combined+'--') } { dynChannel } { ch };
		};
		return audioCollection[0].join( ' ' )
		} +
		'_'+
		// Group
		call{any{"$group"}{fn.match(/(?<=[_-])[^\s_-]+?$/)}{'NA'}.replaceAll(/[-_\[\]]\s*|\.\w{3}$/, '')};
		// Language
		def lang = call{any{'.'+lang}{lang}}+{fn.matches(/(?i).+sdh.+/) ? '_SDH' : ''}{any{fn.match(/(?i)\(foreignpartsonly\)/)}{''}};
		// Extension
		def ext = call{'.'+ext};
		// Call all the bindings to create the result
		(call(main_title).replace(':', ';') + call(lang)).replaceAll(/null/,'')
	}
Will return:
:!: See code above for examples.

Notes about this code:
  • As you can see it truncates the language to 3 letters resulting in [eng, spa] etc.

    :!: Deals with names in files like and retains them (this cannot be gotten by parsing the websites alone) and formats like so:
  • (Director's Cut)
  • (Extended Edition)
  • (Remastered)
  • (25th Anniv. Edition)
  • (Unrated)
  • (Limited Edition)
  • (Uncut)
  • (Collector's Edition)
  • As you can see it truncates the language to 3 letters resulting in [eng, spa] etc.

    :!: Deals with names in files like and retains them (this cannot be gotten by parsing the websites alone) and formats like so:
  • eng.foreignpartsonly.srt
  • eng.SDH.srt (SDH = Subtitles for the deaf or hard-of-hearing)
--============================================================

:!: Don't mind the spaces between expressions. Filebot automatically removes unwanted whitespace characters. It helps me with the readability of the code also. Also there's no filename invalid warnings with these expressions.

I use the airdate before the series because it sorts correctly in WinExplorer and works perfectly with the Kodi app too.

Reason for last edit:
  • 02.05.2019 - Movies only - Re-wrote most of previous movie code to account for the new audio formats.
e.g.
{fn.matches(/(?i).+unrated.+/) ? "String if TRUE" : "String if FALSE"}
There's the matches function which matches the filename in this examples for what's in bold and then ? which is basically asking if true do what in each of the following strings. Then the true and false statements as you see them.
Last edited by stephen147 on 02 May 2019, 21:54, edited 17 times in total.
damonmensch
Posts: 1
Joined: 02 Jan 2016, 17:32

Re: How about sharing our format expressions?

Post by damonmensch »

Here's the formats I use for Plex. I find they work perfectly for it's media scanner with very minimal false matches.

Movies:

Code: Select all

{n.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")} ({y})/{n.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")} ({y}){' - '+vf.replaceAll("360p","SD").replaceAll("240p","LD")}{'.'+lang}
TV Shows: (Doubles for Anime)

Code: Select all

{n.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")}/{n.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")} - S{(episode.special ? 0 : episode.season ? s : 1).pad(2)}E{episode.special ? special.pad(2) : e.pad(2)} - {t.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")}{' - '+vf.replaceAll("360p","SD").replaceAll("240p","LD")}{'.'+lang}
Music:

Code: Select all

{n.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")}\{album.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")}\{pi.pad(2)} - {t.replaceAll(/[:*?"<>|?]/).replaceAll(/[`´‘’?]/, "'")}
Basically all it does is automatically remove any illegal characters for file names, then places movies in "Title (Year)\Title (Year) - Resolution". TV shows in "Show Name\Show Name - SXXEXX - Episode Name - Resolution". Anime does the same as TV Shows except detects if it's a special by the "SX" episode number on anidb and appends "S00", or "S01" instead for normal episodes. This is to get around how plex tries to categorize everything into seasons. Any subtitles automatically get their associated language code added before the extension. Lastly music is sorted into "Album Artist\Album Name\Track - Song Title"

Examples:
Self/less.avi => Self less (2015)\Self less (2015) - 720p.avi
Tremors 3: Back to Perfetion - english.srt =>Tremors 3 Back to Perfection (2001)\Tremors 3 Back to Perfection (2001).eng.srt
Fullmetal Alchemist: Brotherhood - 03 City of Heresy.mkv => Fullmetal Alchemist Brotherhood\Fullmetal Alchemist Brotherhood - S01E03 - City of Heresy - SD.mkv
Darker Than Black - S1 Beneath Cherry Blossoms in Full Bloom.mkv => Darker Than Black\Darker Than Black - S00E01 - Beneath Cherry Blossoms in Full Bloom... - 480p.mkv

Resolution is included for the fact that plex will scan individual files with different resolutions, whether specified in file name or not, and send the appropriate file version based on network conditions and the device itself. Therefore if I had both the 1080p and SD versions of a movie it'll send the 1080p to my smart TV, and the SD to my mobile phone, without any changing of settings on my part.
rwyarbrough
Posts: 1
Joined: 21 Nov 2016, 22:37

Re: How about sharing our format expressions?

Post by rwyarbrough »

Nothing fancy, simple but it works.

I replace the ampersand with the word and, the number sign with the word number, and an regex to remove all special characters except the underscore and dash

Code: Select all

 .replaceAll(/&/,"and").replaceAll(/#/,"number").replaceAll("[^a-zA-Z0-9_-]", "")
if you like umlauts and accents you can use this:

Code: Select all

.replaceAll("[^a-zA-ZÀ-ÿ0-9_-]", "")


I store all my files on a linux server, so I replace the spaces with underscores and remove the left and right parenthesis so I can run remux or other scripts against the files if needed.

Also since some items might not be found, I use { " . $ <parameter> } so I don't end up with extra dots when items are not found so if it doesn't find a value for that parameter, it doesn't print anything -

Code: Select all

{".$source"}
Example with no source available using .{source} :
Mystery_Science_Theater_3000.s02e01.Rocketship_X-M.9-22-1990.480x360..2ch.MP3.360p.XviD.mkv
Example with no source available using {".$source"} :
Mystery_Science_Theater_3000.s02e01.Rocketship_X-M.9-22-1990.480x360.2ch.MP3.360p.XviD.mkv

tv show format:

Code: Select all

{n.space('_').replaceAll(/&/,"and").replaceAll(/#/,"number").replaceAll("[^a-zA-Z0-9_-]", "")}.{s00e00.lower()}.{t.space('_').replaceAll(/&/,"and").replaceAll(/#/,"number").replaceAll("[^a-zA-Z0-9_-]", "").lowerTrail().replacePart('Part_$1')}{".$airdate.month"}{"-$airdate.day"}{"-$airdate.year"}{".$resolution"}{".$source"}{".$af"}{".$ac"}{".$vf"}{".$vc".replace('AVC','x264').replace('HEVC','x265')}
I like using x264 and x265 instead of AVC and HEVC, so I replace on the fly.

Example with parenthesis removed and AVC replaced:
Castle_2009.s08e02.XX_Part_2.9-28-2015.1920x1080.WEB-DL.6ch.AC3.1080p.x264.mkv

music format:

Code: Select all

{artist}.{album}.{pi.pad(2)}_-_{t.space('_').replaceAll(/&/,"and").replaceAll(/#/,"number").replaceAll("[^a-zA-Z0-9_-]", "")}{".[$media.OverallBitrateString]".replaceAll(/null/, "variable")}
media.overallBitrateString will return the kbps value of the digital recording unless its a variable bitrate digital recording which will return "null", so I replace null with the word variable.

movie format:

Code: Select all

{n.space('_').replaceAll(/&/,"and").replaceAll(/#/,"number").replaceAll("[^a-zA-Z0-9_-]", "").lowerTrail().replacePart('Part_$1')}.{y}{".$resolution"}{".$vc"}{".$vf"}{".$source"}{".$ac"}{".$af"}
Pikey18
Posts: 1
Joined: 29 Nov 2016, 08:39

Re: How about sharing our format expressions?

Post by Pikey18 »

The above have been useful for me. My setup is simple - two drives both for TV (movies and music are on other drives).

Code: Select all

{['F:', 'G:'].collect{ (it+'/'+n) as File }.sort{ a, b -> a.exists() <=> b.exists() ?: a.diskSpace <=> b.diskSpace }.last()}/Season {s}/{n} {s00e00} {episode.title}
It sorts new episodes onto the drive that already has the show and if it doesn't exist on either drive onto the one with the most free space.

Naming format is [F:|G:]\ShowName\Season x\ShowName SxxExx EpisodeTitle

File example:

Code: Select all

F:\Chicago P.D\Season 2\Chicago P.D. S02E09 Called In Dead (1).avi
Simple but it works and plex has no issues matching anything that has been run through the above.
roosoos
Posts: 1
Joined: 25 Jan 2017, 12:17

Re: How about sharing our format expressions?

Post by roosoos »

Hi everybody,
I've only come across filebot a week ago now, and after looking through some of the examples on this forum,
I went ahead and started using filebot for renaming music files.
Here is what i've come up so far:

Code: Select all

{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|oundtrack|Best Of|best of|reatest|Remix|remix|ollection/?'':' - '+(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'+'CD)'}
{ext=='mp3'?"":" "+[EXT.upper()]}
{media.'part/position'==null||media.'Part/Position_Total'<'2' ? "" : '/CD'+media.'part/position'}/
{pi.pad(2)+' - '}
{media.'Album/Performer'==media.'Performer' ? "" : (media.'Performer').replaceAll('/',', ')+' - '}
{t.replace(/:/,/,/).replaceAll(/"|`/,/'/)}

what does it do?

1 name artist --> '1 Giant Leap'
2 original year release --> '\1999 - '
3 album title --> 'What About Us'
4 releasetype if not normal album --> ' - Live'
5 part of set? #CD --> ' (2CD)'
6 extension if not mp3 --> ' [M4A]'
7 folder per disc --> '\CD1'
8 tracknumber --> '\01 - '
9 if not albumartist add performer --> '1 Giant Leap feat. Lila Downs & Huun-Huur-Tu - '
10 track title --> 'Come to the Edge'

Which woud make in total:
M:\1 Giant Leap\2009 - What About Me - Live (2CD) [M4A]\CD1\01 - 1 Giant Leap feat. Lila Downs & Huun-Huur-Tu - Come to the Edge.m4a
(if this would be a live recording)
i'm not so sure about the way adding the releasetype looks, i would prefer '(Live)'), but then i would end up with //blah\blahblah (Live) (2CD)\CD1\01 blah.mp3, which doesn't look great either...

Any ideas or comments on how to this more efficient, please let me know.
asc3nti0n
Posts: 6
Joined: 28 Dec 2015, 04:10

Re: [SNIPPET] Sort into A-Z folders

Post by asc3nti0n »

rednoah has been a huge help over the journey, I started using commandline Filebot scripts run from uTorrent(PC) but since going back to Mac, and the uTorrent not handling scripts, I have been hard-coding format of my file directories.

Sorting the Movie and TV Collection by (0-9)-A-Z is most important to me. I extract on a local HDD first, then rename with Filebot (Mac App Store) locally, before performing a synchronising copy (Terminal cp -nRv *) to the samba NAS.
I view my multimedia by Infuse Pro on an Apple TV. It uses the 'trackt' media tracking DB, so it's synchronising between iPads, iPhones and AppleTVs which episodes and Movies have been viewed. (it doesn't have a alphabetical search function, otherwise Infuse has been great, over wired ethernet and wifi)!

But browsing for something to watch is still important, and doing it via alphabetically is inevitably the most easy to do.

I just keep a text file of my favourite renaming formats, in my local and remote media directories.

My TV Episode Code (Local)

Code: Select all

/Users/Guest/Public/TV/{def n00 = any{collection}{n}.sortName().charAt(0); n00.isDigit() ? '0-9' : n00}/{collection+'/'}{n}/{episode.special ? 'Special' : 'Season '+s.pad(2)}/{n} - {episode.special ? 'S00E'+special.pad(2) : s00e00} - {t.replaceAll(/[`´‘’ʻ]/, /'/).replaceAll(/[!?.]+$/).replacePart(', Part $1')} [{airdate}]{' _'+certification+'_'} {hd}
This code will:
  • Place any TV series that starts with a numeral into a folder called '0-9'.
  • Renames "Specials" with the s00exx format.... but they'll live in a folder called Special under the TV Episode Title.
  • Ignore "The " at the start of any TV titles, but still they will appear as the online databases know them as. Also any year suffices are kept.
  • SyyExx for the season and episode formats
  • [yyyy-mm-dd] for the date of first aired, good for searching for "[2017" to check for current TV episodes
  • _Rating_ for the (American) TV classification... useful to decide as you're browsing whether you feel like a dark or light piece of viewing.
They come out as:
/Users/Guest/Public/TV/The Flash (2014)/Season 03/The Flash (2014) - S03E18 - Abra Kadabra [2017-03-28] _TV-PG_.mkv

My TV Episode Code (Remote)

Code: Select all

/Volumes/Multimedia/TV/{def n00 = any{collection}{n}.sortName().charAt(0); n00.isDigit() ? '0-9' : n00}/{collection+'/'}{n}/{episode.special ? 'Special' : 'Season '+s.pad(2)}/{n} - {episode.special ? 'S00E'+special.pad(2) : s00e00} - {t.replaceAll(/[`´‘’ʻ]/, /'/).replaceAll(/[!?.]+$/).replacePart(', Part $1')} [{airdate}]{' _'+certification+'_'} {hd}
Being *nix based, MacOS can address the loaded folder of a remote drive as a finite filepath like this! I figure this isn't obvious to many people, even Mac Users... obviously you linux folk have it well under control. Anyhow, so it's much like looking at a filepath of the Local code... so... onto Movies. Multimedia is the standard top-level media virtual drive for a QNAP NAS... that's what it is... I just mount the QNAP drive every time I boot the mac, and voila, it's always around.

My Movie Code (Local)

Code: Select all

/Users/Guest/Public/Cinema/{def n00 = any{collection}{n}.sortName().charAt(0); n00.isDigit() ? '0-9' : n00}/{collection+'/'}{n}/{n} ({y}){" ["+pi+'of'+pn+']'} _{certification}_ star-{rating} -- {'t-'+minutes} {hd} {'hpi-'+hpi} {'af-'+af} {'vc-'+vc} {'ac-'+ac}
Remote

Code: Select all

/Volumes/Multimedia/Cinema/{def n00 = any{collection}{n}.sortName().charAt(0); n00.isDigit() ? '0-9' : n00}/{collection+'/'}{n}/{n} ({y}){" ["+pi+'of'+pn+']'} _{certification}_ star-{rating} -- {'t-'+minutes} {hd} {'hpi-'+hpi} {'af-'+af} {'vc-'+vc} {'ac-'+ac}
This Movie code will:
  • Bring Movie Collections Together... So Collections are like the Lord of the Rings Trilogy... so I would prefer to browse my collection and see collections together... does make it hard to find some movies you didn't know was in a collection "Minions" is in the "Despicable Me Collection" stored under 'D'... so the code will look for Collection data, if it is present will use that to name the single-letter under "Cinema" and proceed to then name a folder for the movie title, and then go onto naming the individual movie files (mkv, srt, etc.) It's been rather special, and I thank rednoah for his help getting that code to work, a couple of years ago... it's been working a charm ever since!
  • Otherwise, I get the new SD/HD/UHD code from the {hd} data point, that replaces dimension data which I used to use to see if it was 720, 800, 1080, 2160 wide etc... nice addition!
  • If there is multiple pieces of a film (Part 1 and Part 2) I prefer the numeration (1of2) and (2of2) to be shown... they're in the same folder, but still... so that's how it will look. We so rarely use it these days, I now use it as an indicator of whether I have two copies of a film in the folders... happens because I have the star-rating in the filename... so if (1of2) (2of2) pops up, I check the duration (it's there too), and work out which is the better quality (all that data comes through too) and go delete the original file which I don't want to keep... rerun the Match and it sorts it out for me without the (1of2) bit.
  • I think thats, it, I just told you that it's got codec quality, and star rating (I want to update that "star-0.0" notation to what DevXen uses in his 2014 posting (never picked it up before now) {" [$rating" + "★]"} so I'll start trialling that now that's awesome... "star-0.0" is easy to search for "star-9" alphabetically, but since infuse doesn't do numbers, and the trakt database has it's own popularity listing, I rarely use the searchable text functionality of my movie naming convention anymore...
Looks like:
/Users/Guest/Public/Cinema/J/John Wick Collection/John Wick Chapter 2/John Wick Chapter 2 (2017) _R_ star-6.5 -- t-122 HD hpi-792p af-6ch vc-AVC ac-AC3.mkv

Hope that helps anyone with the next level of Sorting their TV and/or Movies alphabetically.

[EDIT: TJL: Yes, the Star character works:]

Code: Select all

/Volumes/Multimedia/Cinema/{def n00 = any{collection}{n}.sortName().charAt(0); n00.isDigit() ? '0-9' : n00}/{collection+'/'}{n}/{n} ({y}){" ["+pi+'of'+pn+']'} _{certification}_ star-{rating+'★'} -- {'t-'+minutes} {hd} {'hpi-'+hpi} {'af-'+af} {'vc-'+vc} {'ac-'+ac}
Makes the "Star-0.0★" bit shine out, being such a dark character, will highlight what is details about the movie and rating before it, and after it is quality data about the file itself, how long the recording is etc.
/Volumes/Multimedia/Cinema/D/Despicable Me Collection/Minions/Minions (2015) _PG_ star-6.4★ -- t-90 HD hpi-1040p af-6ch vc-x264 ac-AC3.mkv
devster
Posts: 417
Joined: 06 Jun 2017, 22:56

Re: How about sharing our format expressions?

Post by devster »

I'll try joining the big ones with my formats.
First of all the command I use:

Code: Select all

filebot -script fn:amc --action test --output "/<disk>/Media" --conflict --def clean=y unsorted=y subtitles=en artwork=y excludeList=".excludes" ut_dir="$ARG_PATH" ut_kind="multi" ut_title="$ARG_NAME" ut_label="$ARG_LABEL" exec="chmod 664 '{file}'" --def @/<disk>/scripts/pushover.txt --def movieFormat=@/<disk>/scripts/movies.groovy seriesFormat=@/<disk>/scripts/tvshows.groovy
I got these mostly thanks to @rednoah and @Ithiel but I just found interesting stuff in DevXen post that I want to add in the near future.
Here's the Movie one:

Code: Select all

{ norm = { it.upperInitial()
             .lowerTrail()
             .replaceTrailingBrackets()
             .replaceAll(/[`´‘’ʻ""“”]/, "'")
             .replaceAll(/[:|]/, " - ")
             .replaceAll(/[?]/, "!")
             .replaceAll(/[*\s]+/, " ")
             .replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
             .replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() })
             .replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/) } }
{ transl = { it.transliterate("Any-Latin; NFD; NFC; Title") }
  isLatin = { java.text.Normalizer.normalize(it, java.text.Normalizer.Form.NFD)
                                  .replaceAll(/\p{InCombiningDiacriticalMarks}+/, "") ==~ /^\p{InBasicLatin}+$/ } }
{ allOf
  {"Movies"}
  // Movies directory
  {n.colon(" - ") + " ($y, $director)"}
  // File name
  { allOf 
    { isLatin(primaryTitle) ? primaryTitle : transl(primaryTitle) }
    {" ($y)"}
    // tags + a few more variants
    { specials = { allOf 
                     {tags}
                     { fn.findAll(/(?i:alternate[ ._-]cut|limited|proper|repack)/)*.upperInitial()*.lowerTrail()*.replaceAll(/[._-]/, " ") }
                     .flatten().sort() }
      specials().size() > 0 ? specials().join(", ").replaceAll(/^/, " - ") : "" }
    {" PT $pi"}
    {" ["}
    { allOf
      // Video stream
      {[vf,vc].join(" ")}
      { allOf
        // Audio stream and language
        {[channels,ac].join(" ")}
        { def a = audioLanguages
          a.size() > 1 ? a.ISO3.join(", ").upperInitial() : a.name.first() }
        .join(" ") }
      {source}
      .join(" - ") }
    {"]"}
    {"-" + group}
    {subt}
    .join("") }
  .join("/") }
Which generates something like:
  • From /<disk>/download/movies/少林足球 (Uncut).mp4 to /<disk>/Media/Movies/Shaolin Soccer (2001, Stephen Chow)/Shǎo Lín Zú Qiú (2001) - Uncut [1080p x264 - 5.1 AAC - Blu-ray].mp4
  • From /<disk>/download/movies/少林足球 (Uncut).eng.srt to /<disk>/Media/Movies/Shaolin Soccer (2001, Stephen Chow)/Shǎo Lín Zú Qiú (2001) - Uncut [1080p x264 - 5.1 AAC - Blu-ray].eng.srt
  • From /<disk>/download/movies/GHOST IN THE SHELL (1995)-FGT.mkv to /<disk>/Media/Movies/Ghost in the Shell (1995, Mamoru Oshii)/GHOST IN THE SHELL (1995) [1080p x264 - 2.0 AC3 Eng, Jpn - BluRay]-FGT.mkv
I'm still trying to mess with the transliteration (it should be "Shàolín Zúqiú", and for some reason TheMovieDB has that horrible title for Ghost in the Shell instead of the correct 攻殻機動隊 which transliterates into Kōkaku Kidōtai), however the result isn't bad.
And here the TV Shows one, this is greener and less polished:

Code: Select all

{ norm = { it.upperInitial()
             .lowerTrail()
             .replaceTrailingBrackets()
             .replaceAll(/[`´‘’ʻ""“”]/, "'")
             .replaceAll(/[:|]/, " - ")
             .replaceAll(/[?]/, "!")
             .replaceAll(/[*\s]+/, " ")
             .replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
             .replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() })
             .replaceFirst(/^(?i)(The)\s(.+)/, /$2, $1/) } } 
{ allOf
  {"TV Shows"}
  { allOf 
      { (norm(n) == norm(primaryTitle)) ? norm(n) : norm(n) + ' [' + norm(primaryTitle) + ']' }
      { "($y)" }
    .join(" ") }
  { episode.special ? 'Specials' : 'Season ' + s.pad(2) }
  { allOf
    { norm(n) }
    { episode.special ? 'S00E' + special.pad(2) : s00e00 }
    { allOf 
      { norm(t) }
      {"PT $pi"}
      { allOf 
        { allOf 
          {"["}
          { allOf
            {[vf,vc].join(" ")}
            {[channels,ac].join(" ")}
            {source}
            .join(" - ") }
          {"]"}
          .join("") }
        {"-$group"}
        {subt}
        .join("") }
      .join(" ") }
    .join(" - ") }
  .join("/") }
And has the following example output:
  • From /<disk>/download/tvshows/Boris - Stagione 1/Boris.1x01.Il mio primo giorno.FFT.sat.ITA.avi to /<disk>/Media/TV Shows/Boris (2007)/Season 01/Boris - S01E01 - Il Mio Primo Giorno [480p DivX - 2.0 MP3]-iTA.avi
  • From /<disk>/download/tvshows/Boris - Stagione 1/Boris.1x02.L'anello del conte.FFT.sat.ITA.avi to /<disk>/Media/TV Shows/Boris (2007)/Season 01/Boris - S01E02 - L'anello Del Conte [480p DivX - 2.0 MP3]-iTA.avi
In this case sat isn't recognized as a source (SatRIP from Sky Italy), and iTA is flagged as the group instead of FFT, but these are minor things.
I only work in black and sometimes very, very dark grey. (Batman)
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: How about sharing our format expressions?

Post by ChefGregS »

I keep this post updated as I fine-tune and update my formats. This latest update is on:
18 January 2019

Here are my formats for Movies and TV Shows. I currently use another app for renaming music files but if I ever change to Filebot for those I'll post mine for that as well.

MOVIES

Code: Select all

 {vf == /2160p/ ? 'N:/Movies 4K' : vf =~ /1080p|720p/ ? 'M:/Movies HD' : 'M:/Movies'}/{n.upperInitial().colon(' - ').replace('?', '!')} {' (' + fn.matchAll(/extended|uncensored|remastered|unrated|uncut|directors.cut|special.edition|redux/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[._]/, " ") + ')'} {any{' Part '+pi}{null}} ({y}) {fn.match(/3D/)}/{n.upperInitial().colon(' - ').replace('?', '!')} {' (' + fn.matchAll(/extended|uncensored|remastered|unrated|uncut|directors.cut|special.edition|redux/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[._]/, " ") + ')'} {any{' Part '+pi}{null}} [{y}, {any{csv('M:/replacecert1.csv').get(certification)}{certification}{"NR"} }, {runtime} Min] {[actors.take(3).join(', ')]} {[genres.take(3).join(', ')]} [{fn.match(/3D/)+', '}{"$vf, $ac@$af"}]{subt} 
This takes this:
Nutty.Professor.II.The.Klumps.2000.1080p.HDDVD.x264.AC3-ETRG.mp4

and changes it to:
M:\Movies HD\Nutty Professor II -The Klumps (2000)/Nutty Professor II -The Klumps (2000) [PG-13, 106 Min] [Eddie Murphy, Janet Jackson, Larry Miller] [Fantasy, Comedy, Romance] [1080p, AC3@6ch].mp4

It takes it from wherever I have it stored and moves it to my Media hard drive and puts it in the correct MOVIE folder. I separate my movies based on resolution. Movies is anything under 720p. Movies HD is anything from 720-2160p. Movies 4K is any movie 2160 and over. It also creates a folder based on the movie title and year. You can easily change the names of the folders or drives in the first section of code.

It shows the rating and runtime then will list up to 3 of the actors, 3 of the genres and then gives information about if the movie is 3D, resolution, audio type and channels.

IF the information is included in the original file name it will also parse and then include in the new name the information such as UNRATED, UNCUT, DIRECTORS CUT, EXTENDED, REMASTERED, UNCENSORED, SPECIAL EDITION, REDUX. You can easily add to this list in the code if you have other version information.

At the end, notice the code {subt}....this will include the correct subtitle extension if Filebot determines the file being renamed is in fact a subtitle file. If the file is NOT a subtitle file this is ignored.

--

TV SERIES

Code: Select all

 O:/TV Series/{n.upperInitial().colon(' - ').replace('?', '!') }/{ any{"Season $s"}{'Specials'} }/{n.upperInitial().colon(' - ').replace('?', '!') } {[genres.take(2).join(', ')]} - {s00e00} - {any{[airdate]}{null}} ({"$vf, $ac@$af"}) - {t.colon(" - ").replace('?', '!')}{subt} 
This will take:
xpats.Bar.Rescue.S05E14.HDTV.XviD-AFG.avi

and create:
M:\TV Series\Bar Rescue\Season 5 [2016, 2017]\Bar Rescue - S05E14 - [2017-02-26] - I Know What You Did Last Summit.avi

The code moves the file(s) into the Media drive under the TV Series folder and then into the SHOW NAME folder. If there is a season associated with the file it puts the file(s) into the season folder. If however, the episode(s) are specials then they will be put into a Specials folder. The file name is the Show Name - season # and episode # - airdate of the episode - name of the episode if there is one.

When it comes to TV series I don't feel the need to have all the video and audio information in the file name. I don't really care. I have debated this, however, a few times as I have a few series where I had to piece together the seasons, thus some episodes in a season may be 720p and some may be 320p and some others 580p. IF I had the video info listed I could more easily either find new ones matching or re-encode myself. But, not really top of my list of things to work on atm. :)
Last edited by ChefGregS on 19 Jan 2019, 03:30, edited 3 times in total.
DevXen
Power User
Posts: 164
Joined: 12 Oct 2014, 21:15

Re: How about sharing our format expressions?

Post by DevXen »

Hey, Thanks for your message, I apologize it took so long to reply, i've been busy with a new job with crazy hours, and had no idea i had a message... I believe this is my latest picard script. I don't really have time to go through and explain all that it does. but it's amazing. I made it for me and how I wanted it. so it'll separate by genre, band, album, disc. (disc name). it'll add extra info to the song as available. (demo, etc) separate soundtracks, various, etc. if an album has more than half of the songs but not a complete album it'll move them to the [unfinished albums] folder. if it has less than 5 songs, they go to the misc folder. Also i didn't realize at the time i had to backup my Variables when it backed up my script. and that PC crashed. so you'll have to go setup the variables it needs. which i'd assume it'll give you errors if they aren't there. I haven't had time to go in and figure those out. as i'm at the moment using a much much simpler script to get my google music songs organized. after i'm done with that i'll go back to this one to finish organizing my main collection. but I wouldn't count on it being anytime soon.


Newest Working version: Separates Incomplete Albums and Misc songs & reads Album/Bonus from album folder

Code: Select all

$set(title,$replace(%title%,...,…))
$set(album,$replace(%album%,...,…))
$set(artist,$replace(%artist%,...,…))
$set(albumartist,$replace(%albumartist%,...,…))
$if(%originaldate%,$set(date,%originaldate%))
$set(filename,%_filename%)
$set(foldername,%_dirname%)

$if($in(%title%,Live),$set(_misctype,Live))
$if($in(%title%,Demo),$set(_misctype,Demos))
$if($in(%title%,Acoustic),$set(_misctype,Acoustic))
$if($in(%title%,Unplugged),$set(_misctype,Acoustic))
$if($in(%title%,Remix),$set(_misctype,Remixes))

$if($in($lower(%_dirname%),album),$if($not(%discsubtitle%),$set(disctitle,Album)))
$if($in(%_dirname%,Bonus),$if($not(%discsubtitle%),$set(disctitle,Bonus Disc)))


$if($gte($matchedtracks(),$div(%totaltracks%,2)),$set(_miscorincomplete,Incomplete),$set(_miscorincomplete,Misc))
$if($gte($matchedtracks(),%totaltracks%),$unset(_miscorincomplete) $unset(_misctype))
$if($lte($sub(%totaltracks%,$matchedtracks()),1),$set(_numberofmissingtracks,$sub(%totaltracks%,$matchedtracks())$unset(_pluaralmissingtracks)))
$if($gt($sub(%totaltracks%,$matchedtracks()),1),$set(_numberofmissingtracks,$sub(%totaltracks%,$matchedtracks())$set(_pluaralmissingtracks,s)))


$if($in(%album%,Tribute),$set(_tribute,Tributes))
$if($in(%album%,tribute),$set(_tribute,Tributes))

$if($eq(%releasetype%,compilation),$set(releasetype,[Compilation Albums]))
$if($eq(%releasetype%,remix),$set(releasetype,[Remixes]) $set(tributetype,[Remixes]))



$if($eq(%releasetype%,soundtrack),$set(releasetype,[Soundtracks]))

$if($eq(%releasetype%,album),$set(releasetype,[Studio Albums]))
$if($eq(%releasetype%,live),$set(releasetype,[Live Albums]))
$if($eq(%releasetype%,single),$set(releasetype,[Singles]))
$if($eq(%releasetype%,ep),$set(releasetype,[EPs]))

$if(%_releasecomment%, $set(_releasecomment,\(%_releasecomment%\)),$noop())
$if($and($eq(%releasecountry%,JP),$not($in(%_releasecomment%,Japan))),$set(_releasecomment,%_releasecomment% \(Japan Import\)))
$if($and($eq(%releasecountry%,RU),$not($in(%_releasecomment%,Russia))),$set(_releasecomment,%_releasecomment% \(Russian Import\)))
$if($and($eq(%releasecountry%,XE),$not($in(%_releasecomment%,Europe))),$set(_releasecomment,%_releasecomment% \(European Import\)))
$if($and($eq(%releasecountry%,AU),$not($in(%_releasecomment%,Australia))),$set(_releasecomment,%_releasecomment% \(Australian Import\)))
$if($and($eq(%releasecountry%,DE),$not($in(%_releasecomment%,German))),$set(_releasecomment,%_releasecomment% \(German Import\)))
$if($and($eq(%releasecountry%,FI),$not($in(%_releasecomment%,Finland))),$set(_releasecomment,%_releasecomment% \(Finland Import\)))
$if($and($eq(%releasecountry%,FR),$not($in(%_releasecomment%,France))),$set(_releasecomment,%_releasecomment% \(France Import\)))



$if($in(%album%, Punk ),$set(tributetype,Punk))
$if($in(%album%, Rock ),$set(tributetype,Rock))
$if($in(%album%, Metal ),$set(tributetype,Metal))
$if($in(%album%, Bluegrass ),$set(tributetype,Bluegrass))
$if($in(%album%, Acoustic ),$set(tributetype,[Acoustic]))
$if($in(%album%,Gothic Acoustic),$set(tributetype,[Gothic Acoustic Series]))
$if($in(%album%,Pickin' On ),$set(tributetype,[Pickin' On Series]))
$if($in(%album%, Industrial ),$set(tributetype,Industrial))
$if($in(%album%, Techno ),$set(tributetype,Techno))
$if($in(%album%,Tribute),$set(_tribute,Tributes))
$if($in(%album%, Quartet ),$set(tributetype,[String Quartet Series]))
$if($in(%album%,Remix),$set(tributetype,[Remixes]))

$if($in(%album%,Symphonic),$set(_tribute,Tributes))
$if($in(%album%,Symphonic),$set(tributetype,[Symphonic]))


$if($in(%album%, Lullaby Renditions),$set(_tribute,Tributes))
$if($in(%album%, Lullaby Renditions),$set(tributetype,[Lullaby Renditions]))

$if($in(%album%, Piano ),$set(_tribute,Tributes))
$if($in(%album%, Piano ),$set(tributetype,[Piano Series]))

$if($not(%tributetype%),$set(tributetype,[Various Artists]))



$if($in(%releasetype%,[Soundtracks]),$set(_tribute,Soundtracks)$unset(tributetype))


$replace($replace($replace($replace($replace($replace($replace($replace($replace(

$if($eq(%compilation%,1),

$if(%_tribute%,[%_tribute%]/
$if(%tributetype%,%tributetype%)/
$if(%date%, [$left(%date%,4)]) - %album%
$if(%_releasecomment%, %_releasecomment%)
$if($and($ne(%totaldiscs%,1),$not($in(%totaldiscs%,1))),\(%totaldiscs% Disc Set\),$noop())
$if($gt(%totaldiscs%,1),/Disc $num(%discnumber%,2)
$if(%discsubtitle%, - \(%discsubtitle%\)))/
$num(%tracknumber%,2) - %artist% - %title%
$if(%discsubtitle%,\(%discsubtitle%\)))

$if($eq(%albumartist%,Various Artists),
$if($not(%_tribute%),Various Artists/%releasetype%/
$if(%date%, [$left(%date%,4)]) - %album%
$if(%_releasecomment%, %_releasecomment%)
$if($and($ne(%totaldiscs%,1),$not($in(%totaldiscs%,1))),\(%totaldiscs% Disc Set\),$noop())
$if($gt(%totaldiscs%,1),/Disc $num(%discnumber%,2)
$if(%discsubtitle%, - \(%discsubtitle%\)))/
$num(%tracknumber%,2) - %artist% - %title%
$if(%discsubtitle%,\(%discsubtitle%\))))

$if($not($eq(%albumartist%,Various Artists)),
$if($not(%_tribute%),Various Artists/%releasetype%/
$if(%date%, [$left(%date%,4)]) - %album%
$if(%_releasecomment%, %_releasecomment%)
$if($and($ne(%totaldiscs%,1),$not($in(%totaldiscs%,1))),\(%totaldiscs% Disc Set\),$noop())
$if($gt(%totaldiscs%,1),/Disc $num(%discnumber%,2)
$if(%discsubtitle%, - \(%discsubtitle%\)))/
$num(%tracknumber%,2) - %artist% - %title%
$if(%discsubtitle%,\(%discsubtitle%\)))))

,*,[x]),?,),:, -),",'),_, ),|, ),<,[),>,]), , )


$replace($replace($replace($replace($replace($replace($replace($replace($replace(

$if($not($eq(%compilation%,1)),
$if(%_tribute%,[%_tribute%]/
$if(%tributetype%,%tributetype%)/
$if(%date%, [$left(%date%,4)]) - %album%$if($ne(%originalyear%,$left(%date%,4)),
$if(%originalyear%, \(%originalyear% Reissue\)))
$if(%_releasecomment%, %_releasecomment%)
$if($and($ne(%totaldiscs%,1),$not($in(%totaldiscs%,1))),\(%totaldiscs% Discs\),$noop())
$if($gt(%totaldiscs%,1),/Disc $num(%discnumber%,2)
$if(%discsubtitle%, - \(%discsubtitle%\)))/
%artist% - $num(%tracknumber%,2) - %title%
$if(%discsubtitle%,\(%discsubtitle%\)))

$if($not(%_tribute%),
$if(%_miscorincomplete%,
$if($eq(%_miscorincomplete%,Misc),
$if2(%grouping%,Unknown)/$if2(%genre%,Unknown)/
$if2(%albumartistsort%,%artistsort%,%albumartist%,%artist%)/
$if(%_misctype%,[%_misctype%]/,[Misc]/)
%artist% -$if(%album%, %album% -) $num(%tracknumber%,2) - %title%)

$if($eq(%_miscorincomplete%,Incomplete),
$if2(%grouping%,Unknown)/$if2(%genre%,Unknown)/
$if2(%albumartistsort%,%artistsort%,%albumartist%,%artist%)/
$if(%_miscorincomplete%, [Incomplete Albums]/)
$if(%date%, [$left(%date%,4)]) - %album% $if(%_numberofmissingtracks%, \($num(%_numberofmissingtracks%,2) Track$if(%_pluaralmissingtracks%,%_pluaralmissingtracks%) Missing\))
$if($ne(%originalyear%,$left(%date%,4)),
$if(%originalyear%, \(%originalyear% Reissue\)))
$if(%_releasecomment%, %_releasecomment%)
$if($and($ne(%totaldiscs%,1),$not($in(%totaldiscs%,1))),\(%totaldiscs% Discs\),$noop())
$if($gt(%totaldiscs%,1),/Disc $num(%discnumber%,2)
$if(%discsubtitle%, - \(%discsubtitle%\)))/
%artist% - $num(%tracknumber%,2) - %title%
$if(%discsubtitle%,\(%discsubtitle%\)))))

$if($not(%_miscorincomplete%),
$if2(%grouping%,Unknown)/$if2(%genre%,Unknown)/
$if2(%albumartistsort%,%artistsort%,%albumartist%,%artist%)/
$if(%releasetype%, %releasetype%/)
$if(%date%, [$left(%date%,4)]) - %album%
$if($ne(%originalyear%,$left(%date%,4)),
$if(%originalyear%, \(%originalyear% Reissue\)))
$if(%_releasecomment%, %_releasecomment%)
$if($and($ne(%totaldiscs%,1),$not($in(%totaldiscs%,1))),\(%totaldiscs% Discs\),$noop())
$if($gt(%totaldiscs%,1),/Disc $num(%discnumber%,2) $if(%disctitle%, - \(%disctitle%\))
$if(%discsubtitle%, - \(%discsubtitle%\)))/
%artist% - $num(%tracknumber%,2) - %title%
$if(%discsubtitle%,\(%discsubtitle%\))))

,*,[x]),?,),:, -),",'),_, ),|, ),<,[),>,]), , )
iAmKoinu
Posts: 4
Joined: 19 Oct 2018, 14:06

Re: How about sharing our format expressions?

Post by iAmKoinu »

Hey there! Been using Filebot for a few months now, and thought I'd share the expressions I have for my collection! :D They're on the simpler side, but it gets the job done for me :)

All of mine are based off of different drives.

Movies:
F:/Movies/{n.lowerTrail().colon(' - ')} ({y})/{n.lowerTrail().colon(' - ')}.[{d.format('MMM-dd-yyyy')}]
Example:
F:/Movies/The Greatest Showman (2017)/The Greatest Showman.[Dec-08-2017].mkv


TV Series:
G:/Shows/n.lowerTrail().colon(' - ')} ({y})/Season {s.pad(2)}/{n.colon(' - ').lowerTrail()}.{y}.{s00e00}.{t.colon(' - ').lowerTrail()}.[{airdate.format('MMM-dd-yyyy')}]
Example:
G:/Shows/How I Met Your Mother (2005)/Season 01/How I Met Your Mother.2005.S01E01.Pilot.[Sep-19-2005].mkv


Anime (I keep my anime in the same directory as my series, because I have them in the same category on Plex.. just easier that way :D ):
G:/Shows/n.lowerTrail().colon(' - ')} ({y})/Season {s.pad(2)}/{n.colon(' - ').lowerTrail()}.{y}.{s00e00}.#{absolute.pad(4)}.{t.colon(' - ').lowerTrail()}.[{airdate.format('MMM-dd-yyyy')}]
Example:
G:/Shows/My Hero Academia (2016)/Season 01/My Hero Academia.2016.S01E01.#0001.Izuku Midoriya Origin.{Apr-03-2016].mkv


As you can see, I like having the series name in the filename itself because I'm weird haha.

Also, the only real difference between TV Series and Anime is that the Anime expression has an added "absolute" numbering added to the filename. I like knowing the episode number, and the S00E00 is for plex :)
I also added a pad of 4 to the absolute numbering, because One Piece is getting up there almost to 1000 episodes, so I just went ahead and made all of the anime absolute numbering with a pad of 4 :)

Anyway, hope this helped some of y'all! :)
snaporaz
Posts: 1
Joined: 27 Apr 2019, 14:53

Re: How about sharing our format expressions?

Post by snaporaz »

I have a simple renaming scheme to organize movies in folders. It distinguishes english names and "foreign" latin and non-latin names:

Code: Select all

{y}/{primaryTitle}{if (n != primaryTitle) {primaryTitle.isLatin() ? " (${n})" : " (${primaryTitle.ascii()}) (${n})"}}/{fn}
Like this:

1993/Short Cuts/Short Cuts.1993.720p.BluRay.AVC-mfcorrea.mkv

1997/Abre los ojos (Open Your Eyes)/Open.Your.Eyes.1997.BluRay.720p.x264.AC3-CMCT.mkv

2018/万引き家族 (wan yinki jia zu) (Shoplifters)/shoplifters.2018.limited.720p.bluray.x264-cadaver.mkv



The only trouble is the non-standard transliteration from non-latin names...
but I can't find an automatic way of applying a correct identifier in String.transliterate(identifier) based on the correct language.
devster
Posts: 417
Joined: 06 Jun 2017, 22:56

Re: How about sharing our format expressions?

Post by devster »

Just an update on formats I'm using, you can now find them here: https://github.com/devster31/filebot-scripts
It includes movie, series, and anime formats as being currently used, however it also has a very small script which can generate them from mustache templates and partials written in javascript, a qBittorrent and transmission post-processing script (in bash and WIP in python), and a few other junk scripts (mostly useless).
Enjoy.
I only work in black and sometimes very, very dark grey. (Batman)
Liquidbings
Posts: 6
Joined: 05 Aug 2019, 21:13

Re: How about sharing our format expressions?

Post by Liquidbings »

TV

Code: Select all

I:/TV/{n}{' '+any{"[$certification]"}{"["+$imdb.certification+"]" }.replaceAll('N A','').replaceAll(/^ \d+$/, 'PG-$0')}{" [$rating" + "★]"}/{regular ? 'Season ' + s.pad(1) : 'Specials'}/
{
	def space = call{' '};
	
	def dir_root = 'I/TV/'+
	call{hd.matches(/(?i)SD/) ? '480p-720p/' : ' '}+
	call{hd.matches(/(?i)HD/) ? '720p-1080p/' : ' '}+
	call{hd.matches(/(?i)UHD/) ? '4k/' : ' '};
	// Main Title e.g.
	// 1408 (2007) (Director's Cut) 1080p HD Blu-ray non-HDR x264 DTS5.1ch_SiNNERS
	// 300 (2007) 720p HD BRRip non-HDR x265 DTS 5.1ch_ESiR
	// Deadpool (2016) 2160p UHD WEB-DL non-HDR AVC DTS-HD MA 7.1ch_DDR
	// Deadpool 2 (2018) (Super Duper Cut) 2160p UHD Blu-ray REMUX HDR10bit ATEME TrueHD Atmos 13Obj 7.1ch_EPSiLON
	def main_title = call{n}+
	space + call{s00e00}+
	space + '-'+
	space + call{t}+
	space + call{fn.matches(/(?i).+\b25th.+?anniv.+/) ? '(25th Anniv. Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\b\(limited\b.*?\).+/) ? '(Limited Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\b\(uncut\b.*?\).+/) ? '(Uncut)' : ' '}+
	space + call{fn.matches(/(?i).+\bcollector.+?s.+?edition\b.+/) ? '(Collector\'s Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\bdirect.+?cut\b.+/) ? '(Director\'s Cut)' : ' '}+
	space + call{fn.matches(/(?i).+\bextended.+?\b.+/) ? '(Extended)' : ' '}+
	space + call{fn.matches(/(?i).+\bextended.+?edit\b.+/) ? '(Extended Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\bimax\b.+/) ? '(IMAX Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\blimited\b.+/) ? '(Limited)' : ' '}+
	space + call{fn.matches(/(?i).+\bremastered\b.+/) ? '(Remastered)' : ' '}+
	space + call{fn.matches(/(?i).+\bsuper.+duper.+cut\b.+/) ? '(Super Duper Cut)' : ' '}+
	space + call{fn.matches(/(?i).+\btheatrical\b.+/) ? '(Theatrical)' : ' '}+
	space + call{fn.matches(/(?i).+\bunrated\b.+/) ? '(Unrated)' : ' '}+
	space + call{any{fn.match(/\([^\()+?[^\d]+?\)\s*/)} {' '}{' '}}+
	space + '['+ call{self.vf ? self.vf : self.hpi}+
	space + call{hd}+
	space + call{source.matches(/(?i)blu.*ray/) ? 'BluRay' : {source} ?: 'WEB-DL'}+
	space + call{fn.matches(/(?i).+\bremux\b.+/) ? 'REMUX' : ' '}+
	space + call{fn.matches(/(?i).+\bwebrip\b.+/) ? 'WEBRip' : ' '}+
	space + call{fn.matches(/(?i).+\bhevc.+?\b.+/) ? '(x265)' : ' '}+
	space + call{fn.matches(/(?i).+\bx265\b.+/) ? '(x265)' : ' '}+
	space + call{fn.matches(/(?i).+\b264\b.+/) ? '(x264)' : ' '}+
	// Only calls {hdr} if it's not SD else non-HDR
	space + call{if (hd =~ 'HD') {any{hdr + bitdepth + 'bit'}{'non-HDR'}}}+
	space + call{vc}+
	space +
	// Call audio
	// Thread here where I got the base code: https://www.filebot.net/forums/viewtopic.php?f=5&t=5285
	call {
		def mCFP =
		[
		'AAC LC SBR PS' : 'AAC',
		'AAC LC SBR' : 'AAC',
		'AAC LC' : 'AAC',
		'AC 3 Dep' : 'E-AC3',
		'AC 3' : 'AC3',
		'DTS 96 24' : 'DTS 96-24',
		'DTS ES XBR' : 'DTS-HD HRA',
		'DTS ES XLL' : 'DTS-HD MA',
		'DTS ES XXCH XBR' : 'DTS-HD HRA',
		'DTS ES XXCH XLL' : 'DTS-HD MA',
		'DTS ES XXCH' : 'DTS-ES',
		'DTS ES' : 'DTS-ES',
		'DTS XBR' : 'DTS-HD HRA',
		'DTS XLL X' : 'DTS X',
		'DTS XLL' : 'DTS-HD MA',
		'DTS' : 'DTS',
		'E AC 3 JOC' : 'EAC3 Atmos',
		'E AC 3' : 'EAC3',
		'MLP FBA 16 ch' : 'TrueHD Atmos',
		'MLP FBA' : 'TrueHD',
		'MP3' : 'MP3',
		'MPEG Audio' : 'MP2',
		'PCM' : 'PCM'
		];
		def audioClean = { it.replaceAll(/[\p{Pd}\p{Space}]/, ' ').replaceAll(/\p{Space}{2,}/, ' ').slash(' ') };
		def channelClean = { it.replaceAll(/Debug.+|Object\sBased\s?\/?|(\d+)?\sobjects\s\/\s|0.(?=\d.\d)|20/).replaceAll(/6/,'5.1').replaceAll(/8/,'7.1') };
		def audioCollection = audio.collect
		{ au ->
			def channels = any{ channelClean(au['ChannelPositionsString2'])}{ channelClean(au['ChannelsOriginal'])}{ channelClean(au['Channels']) };
			def dynChannel = {au['NumberOfDynamicObjects'] + 'Obj'};
			def ch = channels.tokenize('\\/').take(3)*.toDouble().inject(0, { a, b -> a + b }).findAll { it > 0 }.max().toString() + 'ch';
			def codec = audioClean(any{ au['CodecID/Hint'] }{ au['Format'] });
			def format_profile = { ( au['Format_AdditionalFeatures'] != null) ? audioClean(au['Format_AdditionalFeatures']) : '' };
			def combined = allOf{codec}{format_profile}.join(' ');
			def stream = allOf { mCFP.get(combined, 'UNKNOWN_FORMAT--'+combined+'--') } { dynChannel } { ch };
		};
		return audioCollection[0].join( ' ' )
		} +
		'_'+
		// Group
		call{any{"$group"}{fn.match(/(?<=[_-])[^\s_-]+?$/)}{'NA'}.replaceAll(/[-_\[\]]\s*|\.\w{3}$/, '')};
		// Language
		def lang = call{any{'.'+lang}{lang}}+{fn.matches(/(?i).+sdh.+/) ? '_SDH' : ''}{any{fn.match(/(?i)\(foreignpartsonly\)/)}{''}};
		// Extension
		def ext = call{'.'+ext};
		// Call all the bindings to create the result
		(call(main_title).replace(':', ';') + call(lang)).replaceAll(/null/,'')
	}[{runtime} Min]
Movies

Code: Select all

I:/Movies/{n}{' '+any{"[$certification]"}{"["+$imdb.certification+"]" }.replaceAll('N A','').replaceAll(/^ \d+$/, 'PG-$0')}{" [$rating" + "★]"}/
{
	def space = call{' '};
	
	def dir_root = 'I/Movies/'+
	call{hd.matches(/(?i)SD/) ? '480p-720p/' : ' '}+
	call{hd.matches(/(?i)HD/) ? '720p-1080p/' : ' '}+
	call{hd.matches(/(?i)UHD/) ? '4k/' : ' '};
	// Main Title e.g.
	// 1408 (2007) (Director's Cut) 1080p HD Blu-ray non-HDR x264 DTS5.1ch_SiNNERS
	// 300 (2007) 720p HD BRRip non-HDR x265 DTS 5.1ch_ESiR
	// Deadpool (2016) 2160p UHD WEB-DL non-HDR AVC DTS-HD MA 7.1ch_DDR
	// Deadpool 2 (2018) (Super Duper Cut) 2160p UHD Blu-ray REMUX HDR10bit ATEME TrueHD Atmos 13Obj 7.1ch_EPSiLON
	def main_title = call{n}+
	space + call{fn.matches(/(?i).+\b25th.+?anniv.+/) ? '(25th Anniv. Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\b\(limited\b.*?\).+/) ? '(Limited Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\b\(uncut\b.*?\).+/) ? '(Uncut)' : ' '}+
	space + call{fn.matches(/(?i).+\bcollector.+?s.+?edition\b.+/) ? '(Collector\'s Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\bdirect.+?cut\b.+/) ? '(Director\'s Cut)' : ' '}+
	space + call{fn.matches(/(?i).+\bextended.+?\b.+/) ? '(Extended)' : ' '}+
	space + call{fn.matches(/(?i).+\bextended.+?edit\b.+/) ? '(Extended Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\bimax\b.+/) ? '(IMAX Edition)' : ' '}+
	space + call{fn.matches(/(?i).+\blimited\b.+/) ? '(Limited)' : ' '}+
	space + call{fn.matches(/(?i).+\bremastered\b.+/) ? '(Remastered)' : ' '}+
	space + call{fn.matches(/(?i).+\bsuper.+duper.+cut\b.+/) ? '(Super Duper Cut)' : ' '}+
	space + call{fn.matches(/(?i).+\btheatrical\b.+/) ? '(Theatrical)' : ' '}+
	space + call{fn.matches(/(?i).+\bunrated\b.+/) ? '(Unrated)' : ' '}+
	space + call{any{fn.match(/\([^\()+?[^\d]+?\)\s*/)} {' '}{' '}}+
	space + '['+ call{self.vf ? self.vf : self.hpi}+
	space + call{hd}+
	space + call{source.matches(/(?i)blu.*ray/) ? 'BluRay' : {source} ?: 'WEB-DL'}+
	space + call{fn.matches(/(?i).+\bremux\b.+/) ? 'REMUX' : ' '}+
	space + call{fn.matches(/(?i).+\bwebrip\b.+/) ? 'WEBRip' : ' '}+
	space + call{fn.matches(/(?i).+\bhevc.+?\b.+/) ? '(x265)' : ' '}+
	space + call{fn.matches(/(?i).+\bx265\b.+/) ? '(x265)' : ' '}+
	space + call{fn.matches(/(?i).+\b264\b.+/) ? '(x264)' : ' '}+
	// Only calls {hdr} if it's not SD else non-HDR
	space + call{if (hd =~ 'HD') {any{hdr + bitdepth + 'bit'}{'non-HDR'}}}+
	space + call{vc}+
	space +
	// Call audio
	// Thread here where I got the base code: https://www.filebot.net/forums/viewtopic.php?f=5&t=5285
	call {
		def mCFP =
		[
		'AAC LC SBR PS' : 'AAC',
		'AAC LC SBR' : 'AAC',
		'AAC LC' : 'AAC',
		'AC 3 Dep' : 'E-AC3',
		'AC 3' : 'AC3',
		'DTS 96 24' : 'DTS 96-24',
		'DTS ES XBR' : 'DTS-HD HRA',
		'DTS ES XLL' : 'DTS-HD MA',
		'DTS ES XXCH XBR' : 'DTS-HD HRA',
		'DTS ES XXCH XLL' : 'DTS-HD MA',
		'DTS ES XXCH' : 'DTS-ES',
		'DTS ES' : 'DTS-ES',
		'DTS XBR' : 'DTS-HD HRA',
		'DTS XLL X' : 'DTS X',
		'DTS XLL' : 'DTS-HD MA',
		'DTS' : 'DTS',
		'E AC 3 JOC' : 'EAC3 Atmos',
		'E AC 3' : 'EAC3',
		'MLP FBA 16 ch' : 'TrueHD Atmos',
		'MLP FBA' : 'TrueHD',
		'MP3' : 'MP3',
		'MPEG Audio' : 'MP2',
		'PCM' : 'PCM'
		];
		def audioClean = { it.replaceAll(/[\p{Pd}\p{Space}]/, ' ').replaceAll(/\p{Space}{2,}/, ' ').slash(' ') };
		def channelClean = { it.replaceAll(/Debug.+|Object\sBased\s?\/?|(\d+)?\sobjects\s\/\s|0.(?=\d.\d)|20/).replaceAll(/6/,'5.1').replaceAll(/8/,'7.1') };
		def audioCollection = audio.collect
		{ au ->
			def channels = any{ channelClean(au['ChannelPositionsString2'])}{ channelClean(au['ChannelsOriginal'])}{ channelClean(au['Channels']) };
			def dynChannel = {au['NumberOfDynamicObjects'] + 'Obj'};
			def ch = channels.tokenize('\\/').take(3)*.toDouble().inject(0, { a, b -> a + b }).findAll { it > 0 }.max().toString() + 'ch';
			def codec = audioClean(any{ au['CodecID/Hint'] }{ au['Format'] });
			def format_profile = { ( au['Format_AdditionalFeatures'] != null) ? audioClean(au['Format_AdditionalFeatures']) : '' };
			def combined = allOf{codec}{format_profile}.join(' ');
			def stream = allOf { mCFP.get(combined, 'UNKNOWN_FORMAT--'+combined+'--') } { dynChannel } { ch };
		};
		return audioCollection[0].join( ' ' )
		} +
		'_'+
		space+
		// Group
		call{any{"$group"}{fn.match(/(?<=[_-])[^\s_-]+?$/)}{'NA'}.replaceAll(/[-_\[\]]\s*|\.\w{3}$/, '')};
		// Language
		def lang = call{any{'.'+lang}{lang}}+{fn.matches(/(?i).+sdh.+/) ? '_SDH' : ''}{any{fn.match(/(?i)\(foreignpartsonly\)/)}{''}};
		// Extension
		def ext = call{'.'+ext};
		// Call all the bindings to create the result
		(call(main_title).replace(':', ';') + call(lang)).replaceAll(/null/,'')
	}[{runtime} Min]
Hello everyone hope all are well! Very new to all this but I think I have read every page I could and deciphered everything as best I can with my current knowledge.
I took Stephen147's code and modified what I could to output what I was looking for. I had lost everything I did over the last month or so this evening somehow, but was able to rebuild roughly what I had. I believe anway.

Please take a gander and let me know if anyone see's anything that could be cleaned up or fixed as I honestly dont know what a good portion of this stuff does aside from giving me the results I'm looking for lol

I pretty much wanted something that would give me the standard title and season folders with a special for extras/specials
Then tell me the video formats, where it is sourced from, weather it is a remux, what it is encoded to, if it has HDR, then the sound format and channels etc, followed by how long the episode is.

So basically:
Before:
D:/MakeMkv/The.Handmaids.Tale.S03E07.Under.His.Eye.1080p.HULU.WEBRip.AAC2.0.H264/The.Handmaids.Tale.S03E07.Under.His.Eye.1080p.HULU.WEB-DL.AAC2.0.H.264-NTb
After
I:/TV/The Handmaid's Tale [TV-MA] [8.9★]/Season 3/The Handmaid's Tale S03E07 - Under His Eye [1080p HD WEB-DL non-HDR AVC AAC 2.0ch_NTb[55 Min]

Before:
D:/MakeMkv/Rick and Morty S01 Season 1 1080p TrueHD [MAX Quality]/S01E02.Lawnmower.Dog.mkv
After:
I:/TV/Rick and Morty [TV-MA] [9.3★]/Season 1/Rick and Morty S01E02 - Lawnmower Dog [1080p HD non-HDR Microsoft TrueHD 5.1ch_NA[25 Min]

Before:
D:/MakeMkv/Stranger.Things.S01.2160p.BluRay.REMUX.HEVC.DD5.1-FGT/Stranger.Things.S01E01.Chapter.One.The.Vanishing.Of.Will.Byers.2160p.BluRay.REMUX.HEVC.DD5.1-FGT
After:
I:/TV/Stranger Things [TV-14] [9.2★]/Season 1/Stranger Things S01E01 - Chapter One; The Vanishing of Will Byers [2160p UHD BluRay REMUX (x265) non-HDR ATEME AC3 5.1ch_FGT[50 Min]
beambeam
Posts: 11
Joined: 25 May 2019, 22:52

Re: How about sharing our format expressions?

Post by beambeam »

this is my tv and movie torrent complete deluge amc script to work with plex format with some extra format and group info added. also allows you to set base dirs. takes care of unwanted spaces. adds repack/rerip/proper info. fixes permissions.

TV: /path/to/media/tv/Firefly/Season 01/Firefly - S01E01 - Serenity [1080p web-dl avc eac3 repack]-NTG.mkv
MOVIES: /path/to/media/movies/Avatar (2009)/Avatar (2009) [1080p bluray x264 dts]-EVO.mkv

format expression for both tv and movies:
format expression wrote: /path/to/media/tv/or/movies/{plex.derive{' ['}{allOf{vf}{vs}{vc}{ac}{hdr}.join(' ').lower()}{' '+fn.matchAll(/proper|repack|rerip/).join('.').lower()}{']-'}{group}.tail}
please set user vars
deluge torrent complete script:
deluge-postprocess.sh wrote: #!/bin/sh -xu

# plex compatiable filebot rename script w/ extra quality info
# TV: /path/to/media/tv/Firefly/Season 01/Firefly - S01E01 - Serenity [1080p web-dl avc eac3 repack]-NTG.mkv
# MOVIES: /path/to/media/movies/Avatar (2009)/Avatar (2009) [1080p bluray x264 dts]-EVO.mkv

# Input Parameters
ARG_PATH="$3/$2"
ARG_NAME="$2"
ARG_LABEL="N/A"
ARG_SAVE_PATH="$3"

# user vars
movie_dl_dir="flexget-mv" # where deluge downloads movies to (must be different from tv_dl_dir)
tv_dl_dir="flexget-tv" # where deluge downloads tv to (must be different from movie_dl_dir)
exclude_list="/home/ivagsjw/logs/amc.excludes" # this is required or u will get banned. it stores previously processed file list
log_file="/home/ivagsjw/logs/amc.log"
files_out_movies="/data/ivagsjw/f/media/movies"
files_out_tv="/data/ivagsjw/f/media/tv"
files_out_base="/data/ivagsjw/f/media" # base of your media folder with tv and movies dest folder (for fixing chmod permissions)
#### end user vars ###


# check movie or tv
what_label=Series
if [ $(basename "$ARG_SAVE_PATH") = "$movie_dl_dir" ]
then
what_label=Movie
fi

if [ $(basename "$ARG_SAVE_PATH") = "$tv_dl_dir" ] || [ $(basename "$ARG_SAVE_PATH") = "$movie_dl_dir" ]
then
/usr/bin/filebot -script fn:amc --conflict skip --action hardlink -non-strict --log-file "$log_file" --def clean=y ut_dir="$ARG_PATH" ut_kind="multi" ut_title="$ARG_NAME" ut_label="$what_label" "exec=chmod -R a+rwX,o-w $files_out_base" deleteAfterExtract=n excludeList="$exclude_list" movieFormat="$files_out_movies/{plex.derive{' ['}{allOf{vf}{vs}{vc}{ac}{hdr}.join(' ').lower()}{' '+fn.matchAll(/proper|repack|rerip/).join('.').lower()}{']-'}{group}.tail}" seriesFormat="$files_out_tv/{plex.derive{' ['}{allOf{vf}{vs}{vc}{ac}{hdr}.join(' ').lower()}{' '+fn.matchAll(/proper|repack|rerip/).join('.').lower()}{']-'}{group}.tail}"
fi
Post Reply