The adventure of CLI, context menus, and stupid characters

Running FileBot from the console, Groovy scripting, shell scripts, etc
Post Reply
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

The adventure of CLI, context menus, and stupid characters

Post by Ithiel »

So...

I wrote a fancy rename scheme: http://www.filebot.net/forums/viewtopic ... 1205#p7303
Red wrote a fancy windows context menu thing: http://www.filebot.net/forums/viewtopic ... menu#p6514

And I thought "you know what? these two could totally hit it off!"

Turns out.. no.. they hate each other. Now I hate both of them, and a small piece of me has died inside because of how long I've stared at the screen trying to get this stupid thing to work. Partially because of strange characters causing encoding issues, partially because of UNC paths in a batch file causing small kittens to die, and partially because all the omg-so-many-quotes in my rename made everything cry, but all my hamster running last night didn't get me where I was trying to go :-/

However, after a great deal of trial and error, mostly error, I managed to get something that was semi-functional but still had some really weird side effects:

Code: Select all

cmd /c filebot -rename -r "%1" --db TheTVDB -non-strict --log-file context.log --format "//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{imdb.certification}{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|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, \" \") + ')'}{\" Part \$pi\"}{\" [\$vf \$vc \$ac \$af]\"}"
The result - the episode literally renames to this:
\\mynas\media\TV Shows\White Collar (2009 TV-14)\Season 02\White Collar S02E01 Withdrawal Part $pi [$vf $vc $ac $af].avi
It does however 'work' consistently when applied to files with either a local or UNC path, so that's something.

Next, I tried putting the renaming scheme in a text file...

command:

Code: Select all

cmd /c for /f "delims=" %%a in (' type "C:\Program Files\FileBot\cmdlets\tv_shows.txt" ') do (filebot -rename -r "%1" --db TheTVDB -non-strict --log-file context.log --format %%a)
tv_shows.txt (UTF-8 Encoding)

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{imdb.certification}{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|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, \" \") + ')'}{\" Part \$pi\"}{\" [\$vf \$vc \$ac \$af]\"}"
The result? Actually, the first time (when applied in a file that was already in the correct directory), it worked perfectly... then it never worked again. It turns out, it decided to do the following:
\\mynas\media\TV Shows\ (2009 TV-14)\Season 02\ S02E01 Part $pi [$vf $vc $ac $af].avi
I considered that a step backwards, so I decided to try encoding the txt file in unicode... however interestingly, I was back to this again:
\\mynas\media\TV Shows\White Collar (2009 TV-14)\Season 02\White Collar S02E01 Withdrawal Part $pi [$vf $vc $ac $af].avi
But wait!, you say, cmd as a /u flag to say 'i'm unicode!!'... but that didn't help either
i.e. cmd /u /c for .. etc etc ... no joy

So, with the exception of something that randomly worked once and then never worked again, the closest I seem to be able to get is a file that seems to take all the $variables a little too literally.

Much to my annoyance, whenever I actually try and run the whole thing from a batch file, the success is even more limited:

command

Code: Select all

cmd /c "C:\Program Files\FileBot\cmdlets\tv_shows.bat"
tv_shows.bat

Code: Select all

chcp 65001
for /f "delims=" %%a in (' type "C:\Program Files\FileBot\cmdlets\tv_shows.txt" ') do (filebot -rename -r "%1" --db TheTVDB -non-strict --log-file context.log --format %%a)
PAUSE
I tried with and without chcp (and various setings therein), with both my unicode and utf-8 encoded txt file, and both with and without the /u flag, but all it ever got me was:

Code: Select all

NullPointerException: java.lang.NullPointerException
java.lang.NullPointerException
	at net.sourceforge.tuned.FileUtilities.listFiles(FileUtilities.java:402)
	at net.sourceforge.tuned.FileUtilities.listFiles(FileUtilities.java:407)
	at net.sourceforge.tuned.FileUtilities.listFiles(FileUtilities.java:407)
	at net.sourceforge.tuned.FileUtilities.listFiles(FileUtilities.java:392)
	at net.sourceforge.filebot.cli.ArgumentBean.getFiles(ArgumentBean.java:161)
	at net.sourceforge.filebot.cli.ArgumentProcessor.process(ArgumentProcessor.java:74)
	at net.sourceforge.filebot.Main.main(Main.java:192)
Failure (°_°)
(loving the failure face btw, lol)

... so, after about 1,000,000 revisions, and a few more greys, I'm back to basically what I had at the start with the first example, but still no closer to a solution.

AAArrrggggghhh!!!!

Any idea what would be causing it to output [$vf $vc $ac $af] instead of [360p XviD MP3 2ch]?
There can be only one Power² User
User avatar
rednoah
The Source
Posts: 22999
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: The adventure of CLI, context menus, and stupid characte

Post by rednoah »

That's why my context menu samples don't pass in a format, it's crazy!!

Here's what I'd do:

Ignore cmd as much as possible, and do everything in Groovy:

rename1.groovy

Code: Select all

def input  = args[0].isDirectory() ? args[0].listFiles() : args[0]
def format = '''/tripple/quotes/are/the/shizzle'''

rename(file:input, format:format)
This works for files and folders. Because in Groovy you can just put things into tripple quotes you don't have to escape anything.

cmd will be degraded to the minimal job of calling:

Code: Select all

filebot -script rename1.groovy "%1"
:idea: Please read the FAQ and How to Request Help.
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

Re: The adventure of CLI, context menus, and stupid characte

Post by Ithiel »

ah... so I had the right idea trying to call it from a file, but should have been using a groovy file instead.

I haven't tried using groovy files thusfar, so I guess it's probably no wonder I'm running into a new set of errors :-P

command

Code: Select all

cmd /c filebot -script "C:\Program Files\FileBot\cmdlets\tv_shows.groovy" "%1" --db TheTVDB -non-strict --log-file context.log
tv_shows.groovy (UTF-8 as unicode caused even more problems)

Code: Select all

def input  = args[0].isDirectory() ? args[0].listFiles() : args[0]
def format = '''//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{imdb.certification}{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|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, " ") + ')'}{" Part $pi"}{" [$vf $vc $ac $af]"}'''

rename(file:input, format:format)
error:

Code: Select all

MultipleCompilationErrorsException: startup failed:
Script3.groovy: 2: unexpected char: '\' @ line 2, column 202.
   All(/[?]/, "!").replaceAll(/[*\s]+/, " "
                                 ^

1 error

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script3.groovy: 2: unexpected char: '\' @ line 2, column 202.
   All(/[?]/, "!").replaceAll(/[*\s]+/, " "
                                 ^

1 error

	at net.sourceforge.filebot.cli.ScriptShell.evaluate(ScriptShell.java:91)
	at net.sourceforge.filebot.cli.ScriptShell.runScript(ScriptShell.java:85)
	at net.sourceforge.filebot.cli.ArgumentProcessor.process(ArgumentProcessor.java:123)
	at net.sourceforge.filebot.Main.main(Main.java:192)
Failure (°_°)
Is this an escape issue, or a character encoding issue?
There can be only one Power² User
User avatar
rednoah
The Source
Posts: 22999
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: The adventure of CLI, context menus, and stupid characte

Post by rednoah »

haha, backslashes need to bestring escaped, but at least at this point you only need to replace \ with \\


Try the Dollar Slashy $/.../$:

Code: Select all

def format = $/dollar\slashy/is\the/shizzle/$
http://mrhaki.blogspot.tw/2011/04/groov ... lashy.html
:idea: Please read the FAQ and How to Request Help.
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

Re: The adventure of CLI, context menus, and stupid characte

Post by Ithiel »

yeah, I'm totally confused.

do you mean this?

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{imdb.certification}{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|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, " ") + ')'}{" Part $pi"}{" [$vf $vc $ac $af]"}/$
or this?

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{imdb.certification}{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|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, " ") + ')'}{" Part $pi"}{" [$vf $vc $ac $af]"}'''/$
or am I totally misunderstanding you here?

all I know is this...
in Groovy you can just put things into tripple quotes you don't have to escape anything.
you lied lol :-P

and that both of the above attempts to fix this just give me this

Code: Select all

1 error

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script3.groovy: 2: unexpected token: ) @ line 2, column 354.
   t(/^(?i)(The)\s(.+)/, /$2, $1/)}; norm(n
                                 ^

1 error

	at net.sourceforge.filebot.cli.ScriptShell.evaluate(ScriptShell.java:91)
	at net.sourceforge.filebot.cli.ScriptShell.runScript(ScriptShell.java:85)
	at net.sourceforge.filebot.cli.ArgumentProcessor.process(ArgumentProcessor.java:123)
	at net.sourceforge.filebot.Main.main(Main.java:192)
Failure (°_°)
which, granted, is about 100 characters further along before bombing out, but still doesn't seem to get it across the line >.<
There can be only one Power² User
User avatar
rednoah
The Source
Posts: 22999
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: The adventure of CLI, context menus, and stupid characte

Post by rednoah »

haha, there was some /$ and $/ in the code that mess it up even with dollar slashy! :D

OK, last resort, make a text file with your format:

Code: Select all

def format = new File('path/to/format.txt').getText()
:idea: Please read the FAQ and How to Request Help.
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

Re: The adventure of CLI, context menus, and stupid characte

Post by Ithiel »

yay - it worked!

command:

Code: Select all

@="cmd /c filebot -script \"C:\\Program Files\\FileBot\\cmdlets\\tv_shows.groovy\" \"%1\" --db TheTVDB -non-strict --log-file context.log"
tv_shows.groovy

Code: Select all

def input  = args[0].isDirectory() ? args[0].listFiles() : args[0]
def format = new File('C:\\Program Files\\FileBot\\cmdlets\\tv_shows.txt').getText()

rename(file:input, format:format)
tv_shows.txt

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{imdb.certification}{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|special[ ._-]edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[.]/, " ") + ')'}{" Part $pi"}{" [$vf $vc $ac $af]"}

UPDATE - Final context menu script can be found here: http://www.filebot.net/forums/viewtopic.php?f=3&t=1222
There can be only one Power² User
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

Re: The adventure of CLI, context menus, and stupid characte

Post by Ithiel »

argh... I've just done some testing and I've noticed that while the rename from the folder level will scan/rename files within that folder, it won't scan files within sub folders of that folder.

i.e. If you right click on "N:\TV Shows\The Adventures of Random Show\Season 01\" and click 'Rename -> TV Shows (theTVDB), that will scan and rename the files therein.
... however, if you right click on "N:\TV Shows\The Adventures of Random Show\" and click 'Rename -> TV Shows (theTVDB), it won't detect the files in the sub folder 'Season 01'.

corresponding context code:

Code: Select all

cmd /c filebot -script "https://raw.github.com/CapriciousSage/scripts/master/tv_shows.groovy" "%1" --db TheTVDB -non-strict --log-file context.log
corresponding groovy code:

Code: Select all

myFile = new File("C:\\Program Files\\FileBot\\cmdlets\\output.txt")

def input  = args[0].isDirectory() ? args[0].listFiles() : args[0]
def format = new URL('https://raw.github.com/CapriciousSage/schemes/master/tv_shows.txt').getText()

def output = myFile.readLines().get(1)

rename(file:input, format:format, output:output)
Any thoughts on how I can get it to scan all sub folders as well (or is that opening up a whole new can of worms)?
There can be only one Power² User
User avatar
rednoah
The Source
Posts: 22999
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: The adventure of CLI, context menus, and stupid characte

Post by rednoah »

Get files from sub folders as well:

Code: Select all

args[0].getFiles()
At this point you can just do this, this will work for folders and single files like you said:

Code: Select all

def input = args.getFiles()
:idea: Please read the FAQ and How to Request Help.
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

Re: The adventure of CLI, context menus, and stupid characte

Post by Ithiel »

thanks - is that in addition or as a replacement to the existing line 3 'def input'?

Or, to have it work for either files or folders, would I need to make it this?

Code: Select all

def input  = args[0].isDirectory() ? args[0].getFiles() : args[0]
(swapping out listFiles for getFiles)
There can be only one Power² User
User avatar
rednoah
The Source
Posts: 22999
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: The adventure of CLI, context menus, and stupid characte

Post by rednoah »

Swap it out:

Code: Select all

def input  = args.getFiles()
if args is a single file you'll get back the single file as list, if it's a folder you'll get the subfiles as list
:idea: Please read the FAQ and How to Request Help.
User avatar
Ithiel
Power² User
Posts: 204
Joined: 11 Jul 2013, 14:58

Re: The adventure of CLI, context menus, and stupid characte

Post by Ithiel »

hah - seems to do the trick :-)

Updating the GitHub groovy files now.
There can be only one Power² User
Post Reply