Has anyone made any scripts for Plex media file naming and sorting?

I have been trying to learn Applescript for 20 years. That should tell you something about how useless I am.

But I’m always coming up with reasons to finally get serious about it, seeing as how I’m an automation freak.

Latest is renaming files for Plex.

What I would love to do is two main things.

First, a pretty simple rename: search file names for anything like digit.digit or digit digit.digit digit or Season digit Episode digit and change all such things into “SDIGITEDIGIT” ya know, 1.22 to S01E22 or 3.5 to S03E05…

But even more than that, which I can kinda do to some extent with various renaming tools, would be THIS:

Manually select 2 or more episodes of a television show, which already have partly the same name, i.e.: The Walking Dead SE01E07.mkv and The Walking Dead S01E12.avi, for instance.

Then a script would take over via whatever means and would:

¢Create new folder containing the two items.

¢Name the folder after, say, the first 15 characters of the first file. (Or anything else that indicates the folder contains something specific, not just “new folder with items” which I then have to change)

¢Create a folder within that folder named “Season 1”

¢move the items into that folder

Of course if I had the scripting abilities i would probably spend hours getting even more detailed, coming up with ways to automatically name the folder better, create other season folders automatically based on the names of the files…stuff like that.

Have any of you insanely talented and able folks done anything like this for your OWN Plex needs, something you can share? Any ideas how I could exploit Automator or Keyboard Maestro to do something like this?

Hi,

this is a starting point for the renaming part.

First of all, install Satimage OSAX from here

It’s a scripting addition containing a find command which supports regular expression search.

The script looks for digit(digit).digit(digit) in the string and replaces it with SxxExx


set showString to "The Walking Dead 1.22.mkv"

set findResult to find text "\\d+?\\.\\d+" in showString with regexp
set startPosition to findResult's matchPos
set endPosition to ((findResult's matchLen) + startPosition)
set seasonInfo to findResult's matchResult
tell showString to set {prefix, suffix} to {text 1 thru startPosition, text (endPosition + 1) thru -1}
set {TID, text item delimiters} to {text item delimiters, "."}
set {season, episode} to text items of seasonInfo
set text item delimiters to TID

set newString to prefix & "S" & pad(season) & "E" & pad(episode) & suffix


on pad(v)
	return text -2 thru -1 of ("00" & v)
end pad

Then the title portion “ to be used as the folder name “ is

set title to text 1 thru -2 of prefix

–I created this to organize my TV Show folder
–Replace “Time Machine Backups:TVShows:” with your directory
–this will sort files by Title Folder/Season Folder
–if the file does not contains S## then it will move file to a folder called TITLE ERROR
–duplicate file names will be replaced
–empty folders will be deleted and the trash will be emptied
set list_TVShows to {}
tell application “System Events”
set list_TVShows to (get the name of every folder of folder “Time Machine Backups:TVShows:”)
end tell

tell application “Finder”
set TVShowFolder to folder “Time Machine Backups:TVShows:”
set tvshowFiles to (every file in entire contents of TVShowFolder)

repeat with thisItem in tvshowFiles
	
	set thename to (name of thisItem)
	
	if thename contains " S0" then
		set AppleScript's text item delimiters to " S0"
	else
		if thename contains " S1" then
			set AppleScript's text item delimiters to " S1"
		else
			if thename contains " S2" then
				set AppleScript's text item delimiters to " S2"
			else
				if thename contains " S3" then
					set AppleScript's text item delimiters to " S3"
				else
					if thename contains " S4" then
						set AppleScript's text item delimiters to " S4"
					else
						if thename contains " S5" then
							set AppleScript's text item delimiters to " S5"
						else
							if thename contains " S6" then
								set AppleScript's text item delimiters to " S6"
							else
								if thename contains " S7" then
									set AppleScript's text item delimiters to " S7"
								else
									if thename contains " S8" then
										set AppleScript's text item delimiters to " S8"
									else
										if thename contains " S9" then
											set AppleScript's text item delimiters to " S9"
											
										end if
									end if
								end if
							end if
						end if
					end if
				end if
			end if
		end if
	end if
	
	if thename contains " (" then
		set seriesname to "**TITLE ERROR**"
	else
		set seriesname to get text item 1 of thename
	end if
	try
		make new folder at TVShowFolder with properties {name:seriesname}
	end try
	set TVShowFolder to TVShowFolder as string
	set seriesname to seriesname as string
	set tvshow_seriesname to TVShowFolder & seriesname as string
	tell application "Finder"
		
		set seriesfolder to folder tvshow_seriesname
	end tell
	
	set the_fileseason to thename
	
	set t to the_fileseason
	if the_fileseason contains " S0" then
		set theSeason to get my extractBetween(t, seriesname & " S0", "E")
	else
		set theSeason to get my extractBetween(t, seriesname & " S", "E")
	end if
	
	set list_series to (get the name of every folder of folder (seriesfolder as string))
	if the_fileseason does not contain " S" then
		
		move thisItem to TVShowFolder & seriesname as string
	else
		
		if list_series does not contain "Season " & theSeason as string then
			make new folder at (TVShowFolder & seriesname & ":" as string) with properties {name:"Season " & theSeason as string}
		end if
		move thisItem to TVShowFolder & seriesname & ":" & "Season " & theSeason as string with replacing
		
	end if
	
end repeat

set pathoffolder to TVShowFolder as alias
--change folder here
tell application "Finder"
	repeat with oneFolder in (get folders of pathoffolder)
		if (count items) of oneFolder is 0 or ((count items) of oneFolder is 1 and name of item 1 of oneFolder starts with ".") then delete oneFolder
	end repeat
	empty trash
end tell

end tell

---- The handler ----
to extractBetween(SearchText, startText, endText)
set tid to AppleScript’s text item delimiters – save them for later.
set AppleScript’s text item delimiters to startText – find the first one.
set endItems to text of text item -1 of SearchText – everything after the first.
set AppleScript’s text item delimiters to endText – find the end one.
set beginningToEnd to text of text item 1 of endItems – get the first part.
set AppleScript’s text item delimiters to tid – back to original values.
return beginningToEnd – pass back the piece.
end extractBetween

Hi kearney194.

Thanks for posting your script. If you’re open to a few suggestions:

  1. That massive ‘if . else’ block could be made less bulky using an ‘else if’ construction:
if thename contains " S0" then
	set AppleScript's text item delimiters to " S0"
else if thename contains " S1" then
	set AppleScript's text item delimiters to " S1"
else if thename contains " S2" then
	set AppleScript's text item delimiters to " S2"
else if thename contains " S3" then
	set AppleScript's text item delimiters to " S3"
else if thename contains " S4" then
	set AppleScript's text item delimiters to " S4"
else if thename contains " S5" then
	set AppleScript's text item delimiters to " S5"
else if thename contains " S6" then
	set AppleScript's text item delimiters to " S6"
else if thename contains " S7" then
	set AppleScript's text item delimiters to " S7"
else if thename contains " S8" then
	set AppleScript's text item delimiters to " S8"
else if thename contains " S9" then
	set AppleScript's text item delimiters to " S9"
end if

Or another idea might be to let the script save you the typing:

repeat with i from 0 to 9
	set AppleScript's text item delimiters to " S" & i
	if (count thename's text items) > 1 then exit repeat
end repeat
  1. The ‘if . else’ block immediately after that only uses the text item delimiter result if thename doesn’t contain " (“. So it would be more efficient to do that test first to save having to do the other tests if " (” turns up. The first two ‘if’ blocks could then be combined and reduced to:
if thename contains " (" then
	set seriesname to "**TITLE ERROR**"
else
	repeat with i from 0 to 9
		set AppleScript's text item delimiters to " S" & i
		if (count thename's text items) > 1 then exit repeat
	end repeat
	set seriesname to text item 1 of thename
end if
  1. It’s considered good practice to reset the text item delimiters after use, either to their default value or to what they were before you changed them, so:
if thename contains " (" then
	set seriesname to "**TITLE ERROR**"
else
	set tid to AppleScript's text item delimiters
	repeat with i from 0 to 9
		set AppleScript's text item delimiters to " S" & i
		if (count thename's text items) > 1 then exit repeat
	end repeat
	set seriesname to text item 1 of thename
	set AppleScript's text item delimiters to tid
end if
  1. What I said in point 2. above similarly applies to the next two ‘if . else’ blocks. It’s better to test for the_fileseason containing " S" before checking or taking any “S”-related action based on whether or not it contains “S0” and before getting a load of folder names that you may not actually need:
if the_fileseason contains " S" then
	
	If the_fileseason contains " S0" then
		set theSeason to my extractBetween(the_fileseason, seriesname & " S0", "E")
	else
		set theSeason to my extractBetween(the_fileseason, seriesname & " S", "E")
	end if
		
	set list_series to (the name of every folder of seriesfolder)
		
	if list_series does not contain "Season " & theSeason then
		make new folder at folder (TVShowFolder & seriesname) with properties {name:"Season " & theSeason}
	end if
	move thisItem to folder (TVShowFolder & seriesname & ":" & "Season " & theSeason) with replacing
else -- the_fileseason does not contain " S".

	move thisItem to folder (TVShowFolder & seriesname)
		
end if
  1. I myself would regard the parenthesis in ‘if (count items) of oneFolder is 0’ as incorrect, although the expression seems to work. Notionally, the ‘count’ command counts the ‘items of oneFolder’. It’s not some (count items) property being read off from the folder. Less misleading would be ‘if (count items of oneFolder) is 0’. Or, since an ‘item’ is the default kind of object in a folder, just ‘if (count oneFolder) is 0’.

  2. In the handler, the two instances of ‘text of’ are superfluous. The variables should be set directly to the text items

to extractBetween(SearchText, startText, endText)
	set tid to AppleScript's text item delimiters -- save them for later.
	set AppleScript's text item delimiters to startText -- find the first one.
	set endItems to text item -1 of SearchText -- everything after the first.
	set AppleScript's text item delimiters to endText -- find the end one.
	set beginningToEnd to text item 1 of endItems -- get the first part.
	set AppleScript's text item delimiters to tid -- back to original values.
	return beginningToEnd -- pass back the piece.
end extractBetween

The handler, by the way, assumes that there’s only one instance of startText (or none) in SearchText or that the text to be extracted comes after the last instance.

  1. When posting AppleScript code on MacScripter, would you mind wrapping it in our special [applescript] and [/applescript] tags? There’s a button for them just above the text window on the posting page. They make the code appear in a box with a clickable link, as above.

Hope this is helpful.