Skip to content

Instantly share code, notes, and snippets.

@chazlarson
Forked from mblythe86/plex_cleanup.rb
Created April 20, 2022 17:52
Show Gist options
  • Save chazlarson/c48afeecfa88703e3d10f497c544b73f to your computer and use it in GitHub Desktop.
Save chazlarson/c48afeecfa88703e3d10f497c544b73f to your computer and use it in GitHub Desktop.
Clean unused posters/art/banners from Plex
#!/usr/bin/env ruby
# At least for movies, it looks like it copies the 'selected' stuff into the
# _stored/ folder. It also seems to use the _combined/ folder for access.
# so, I shoud be able to delete anything that's not those two.
# And after that, in the _combined folder, I can/should delete any broken links
# and remove them from <art> and <posters> in Info.xml.
# remove <reviews> from Info.xml too, since it seems to be unused.
# As far as I can tell, extras.xml can just be deleted?
# Same for Artists
# In Albums, similar, but just 'posters'.
# Probably just delete 'lyrics' because it's also unused?
# TV Shows similar - art, banners, posters, themes. seasons is probably more complicated - need to revisit.
require 'pathname'
require 'nokogiri'
metadata = Pathname.new('/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Metadata/')
['Albums','Movies','TV Shows','Artists'].each do |dir|
puts dir
(metadata+dir).each_child do |a|
puts a.basename
a.each_child do |path|
path += 'Contents'
next unless path.exist?
path.each_child do |dir|
dir.rmtree unless ['_stored','_combined'].include? dir.basename.to_s
end
path += '_combined'
#delete extras.xml
extras = path + 'extras.xml'
extras.unlink if extras.exist?
#open _combined/Info.xml
next unless (path + 'Info.xml').exist?
info_file = (path + 'Info.xml').to_s
info_xml = File.open(info_file){|f| Nokogiri::XML(f)}
#remove <reviews><item> and <lyrics><items> from Info.xml
['reviews','lyrics'].each do |type|
info_xml.search("//#{type}/item").each{|i| i.remove}
info_xml.search("//#{type}").each{|n| n.inner_html = n.inner_html.gsub(/\n\s*\n/,'')}
end
['art','banners','posters','themes'].each do |type|
next unless (path+type).exist?
(path + type).each_child do |link|
next unless link.symlink?
unless link.exist?
name = link.basename.to_s
link.unlink #delete broken symlink
#remove from Info.xml
info_xml.search("//#{type}/item[@preview='#{name}']").remove
info_xml.search("//#{type}/item[@media='#{name}']").remove
end
end
info_xml.search("//#{type}").each{|n| n.inner_html = n.inner_html.gsub(/\n\s*\n/,'')}
end
#write Info.xml
File.open(info_file, 'w'){|f| f.write info_xml.to_xml}
end
end
end
@chazlarson
Copy link
Author

Here's the reddit comment referenced upstream:

I just wrote a script to do this. It seems to work OK for me - it didn't break anything in Plex as far as I can tell, anyway. It didn't save as much disk space as I was hoping, but maybe I can improve it over time.

Note that I run Plex under Linux, so I'm using the Linux file path - the code will have to be updated to work on Windows. I also don't have PlexPass, so the script might be overzealous about deleting data for PlexPass features (e.g. movie extras, song lyrics).

I'll probably start running this as a cron to regularly clean stuff up as I add more media. I'm thinking that I'll keep around a backup of the Plex dir in case I break anything, too:

service plexmediaserver stop
rm -rf /var/lib/plexmediaserver.bak
cp -al /var/lib/plexmediaserver /var/lib/plexmediaserver.bak
plex_cleanup.rb
service plexmediaplayer start

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment