Add Post-Processing Scripts via Rename Settings
You can add custom post-processing scripts via Renaming Settings ➔ Post Process ➔ New Script.Use Right-Click ➔ Run or CTRL+R to do a test run and check debug output:
Add Post-Processing Scripts via the --apply option from Terminal
--apply can be added to -rename, -find and -mediainfo commands to run your custom code on newly renamed files or previously renamed files.Shell: Select all
--apply '{ source, target, metadata -> println "$source | $target | $metadata" }'
Shell: Select all
--apply /path/to/apply.groovy
e.g. Run Command
Run Command after processing:Groovy: Select all
system 'say', '-v', 'Trinoids', 'Rename Complete'
Groovy: Select all
system '/path/to/script.sh', *args
Groovy: Select all
{ source, target ->
system '/path/to/script.sh', source, target
}
e.g. Refresh Plex
Refresh Plex via a HTTP request with X-Plex-Token authentication:Groovy: Select all
def host = '127.0.0.1'
def auth = 'YOUR_PLEX_TOKEN'
curl "http://${host}:32400/library/sections/all/refresh?X-Plex-Token=${auth}"
e.g. Refresh Plex (Partial Scan)
Refresh Plex via dedicated HTTP requests for each library and target folder path:Groovy: Select all
def host = '127.0.0.1'
def auth = 'YOUR_PLEX_TOKEN'
def sections = "http://${host}:32400/library/sections"
def header = ['X-Plex-Token': auth]
// request library sections
def libraryRoot = [:].withDefault{ [] }
curl(header, sections).'Directory'.'Location'.collect{ location ->
def key = location.'..'.'@key'.text()
def path = location.'@path'.text()
def root = path.split(/[\\\/]/).last()
libraryRoot[root] += [key: key, path: path]
}
// guess remote file path
def requests = [] as Set
args.collect{ f -> f.dir.path.split(/[\\\/]/).tail() }.unique().each{ components ->
components.eachWithIndex{ c, i ->
libraryRoot[c].each{ r ->
if (i < components.size() - 1) {
requests += [section: r.key, path: [r.path, *components[i+1..-1]].join('/')]
} else {
requests += [section: r.key, path: r.path]
}
}
}
}
// send refresh requests
requests.each{ r ->
curl(header, "${sections}/${r.section}/refresh".toURL(path: r.path))
}
e.g. Refresh Emby / Jellyfin
Refresh Emby / Jellyfin via a HTTP request:Groovy: Select all
def host = '127.0.0.1'
def auth = 'YOUR_API_KEY'
curl "http://${host}:8096/Library/Refresh?api_key=${auth}", [:]
e.g. Refresh Kodi
Refresh Kodi via a HTTP request:Groovy: Select all
def host = '127.0.0.1'
def port = 8080
curl "http://${host}:${port}/jsonrpc", [jsonrpc: '2.0', method: 'VideoLibrary.Scan', id: 1]
e.g. Refresh Radarr
Refresh Radarr via HTTP requests:Groovy: Select all
def host = '127.0.0.1'
def port = 8310
def auth = 'YOUR_API_KEY'
def ids = model.findAll{ it.type =~ /Movie/ }.findResults{ it.tmdbId } as Set
ids.each{ id ->
def r = curl "http://${host}:${port}/api/v3/movie?tmdbId=${id}", 'X-Api-Key': auth
r.each{ m ->
curl "http://${host}:${port}/api/v3/command", [name: 'rescanMovie', movieId: m.id], 'X-Api-Key': auth
}
}
e.g. Refresh Sonarr
Refresh Sonarr via HTTP requests:Groovy: Select all
def host = '127.0.0.1'
def port = 8989
def auth = 'YOUR_API_KEY'
def ids = model.findAll{ it.type =~ /Episode/ }.findResults{ it.tvdbId } as Set
ids.each{ id ->
def r = curl "http://${host}:${port}/api/v3/series?tvdbId=${id}", 'X-Api-Key': auth
r.each{ s ->
curl "http://${host}:${port}/api/v3/command", [name: 'rescanSeries', seriesId: s.id], 'X-Api-Key': auth
}
}
e.g. Notify via Discord
Send alerts to a Discord channel via Server Settings ➔ Integrations ➔ Webhooks:Groovy: Select all
{ source, target ->
curl 'https://discord.com/api/webhooks/YOUR_WEBHOOK', [content: """```[${action}] from [${source.name}] to [${target.name}]```"""]
}
e.g. Notify via Mattermost
Send alerts to a Mattermost channel via Incoming Webhooks:Groovy: Select all
{ source, target ->
curl 'http://YOUR_SITE/hooks/YOUR_WEBHOOK', [text: """```[${action}] from [${source.name}] to [${target.name}]```"""]
}
e.g. Set xattr metadata on source files
Set xattr metadata on the source file as well:Groovy: Select all
{ source, target, metadata ->
source.metadata = metadata
}
e.g. Add subtitles in multiple languages
Fetch subtitles in multiple languages via Exact Search if possible or Fuzzy Search if necessary:Groovy: Select all
{ source, target ->
getSubtitles target, 'en', 'de', 'fr', strict:false
}
e.g. Delete duplicates
Delete logical duplicates that are of lower quality from the target folder if the newly added file is of better quality:Groovy: Select all
{ source, target, metadata ->
target.dir.listFiles{ it.video && it != target && it.metadata == metadata }.each{
if (target.isBetter(it)) {
trash(it)
} else {
reveal(it)
}
}
}
e.g. Delete clutter files
Delete *.txt files and *.nfo files from the source folder:Groovy: Select all
{ source, target ->
trash source.dir.listFiles{ it.extension ==~ /txt|nfo/ }
}
e.g. Set Finder Comments
Run osascript to set the Finder Comments to the original file name:Groovy: Select all
{ source, target ->
// reveal file in Finder
system 'open', '-R', target
// set Finder Comment
system 'osascript', '-e', """
tell app "Finder"
set f to (POSIX file "$target" as alias)
set c to "$original"
set comment of f to c
end tell
"""
}
e.g. Set Media Title
Run mkvpropedit or AtomicParsley to set the media title property to the original file name:Groovy: Select all
{ source, target ->
if (ext == /mkv/) {
system 'mkvpropedit', target, '--edit', 'info', '--set', "title=$original"
}
if (ext == /mp4/) {
system 'AtomicParsley', target, '--title', original, '--overWrite'
}
}
e.g. Hello World
The Hello World example that will get you started with any possible custom use case:Groovy: Select all
// RUN ONCE
{
println "args = $args" // args ... list of target files
println "model.n = $model.n" // model.* ... any binding for all matches
println "model.f = $model.f" // ⋮
println "action = $action" // action ... move, copy, etc
}
// RUN ONCE FOR EACH FILE
{ source, target, metadata ->
println "source = $source" // source ... source file
println "target = $target" // target ... target file
println "metadata = $metadata" // metadata ... movie, episode, etc
println "n = $n" // * ... any binding for this match
println "type = $type" // ⋮
println "f = $f" // ⋮
println "ext = $ext" // ⋮
}