Difference between revisions of "Find orphans.py"
From MythTV Official Wiki
m |
m |
||
Line 6: | Line 6: | ||
|category=Maintenance | |category=Maintenance | ||
|file=find_orphans.py | |file=find_orphans.py | ||
− | |S24}} | + | |S24=yes}} |
This script is a '''"safe"''' alternative to the old [[Myth.find_orphans.pl]] script. It is informative only, showing any missing videos, or unknown files. It can handle multiple backends, and does not need to be run locally, however recordings stored on offline backends will be marked as orphaned. | This script is a '''"safe"''' alternative to the old [[Myth.find_orphans.pl]] script. It is informative only, showing any missing videos, or unknown files. It can handle multiple backends, and does not need to be run locally, however recordings stored on offline backends will be marked as orphaned. |
Revision as of 01:13, 12 November 2010
Note: The correct title of this article is find_orphans.py. It appears incorrectly here due to technical restrictions.
Author | Raymond Wagner |
Description | A scanner to look for missing and unknown recording files. This is informative only, informing the user of the files but taking no action. |
Supports |
This script is a "safe" alternative to the old Myth.find_orphans.pl script. It is informative only, showing any missing videos, or unknown files. It can handle multiple backends, and does not need to be run locally, however recordings stored on offline backends will be marked as orphaned.
>./find_orphans.py Recordings with missing files Undercovers - Devices 4642_20101006201300.mpg Orphaned video files mythbe:/srv/mounts/twotb_1/video/2054_20080225110000.mpg 2.5GB Total: 2.5GB Orphaned snapshots myth0:/srv/mounts/myth0_1/video/4122_20101013113500.mpg.png 2.6KB mythbe:/srv/mounts/twotb_1/video/2029_20100409024900.mpg.png 84.9KB mythbe:/srv/mounts/twotb_1/video/2047_20100807180500.mpg.png 92.9KB mythbe:/srv/mounts/twotb_1/video/2059_20100630090000.mpg.png 87.0KB Total: 267.4KB Database backups mythbe:/mnt/mythtv/store/backups/mythconverg--20101007134000.sql 17.3MB mythbe:/mnt/mythtv/store/backups/mythconverg-1254-20100902174922.sql.gz 13.1MB mythbe:/mnt/mythtv/store/backups/mythconverg-1263-20100913163154.sql 62.1MB mythbe:/mnt/mythtv/store/backups/mythconverg-1263-20100913163216.sql.gz 13.0MB mythbe:/mnt/mythtv/store/backups/mythconverg-1263-20101007134659.sql.gz 15.9MB mythbe:/mnt/mythtv/store/backups/mythconverg-1264-20101008023651.sql.gz 16.5MB Total: 137.9MB Other files mythbe:/srv/mounts/twotb_1/video/4121_20100312215900.mpg.tmp 398.6MB mythbe:/srv/mounts/twotb_1/video/4191_20090928200000.mpg.tmp 2.4GB mythbe:/srv/mounts/twotb_1/video/4191_20091005195900.mpg.tmp 2.6GB mythbe:/srv/mounts/twotb_1/video/4642_20101006201300.mpg.1 4.9GB Total: 10.2GB
#!/usr/bin/env python from MythTV import MythDB, MythBE from socket import timeout import os import sys class File( str ): def __new__(self, host, group, path, name, size): return str.__new__(self, name) def __init__(self, host, group, path, name, size): self.host = host self.group = group self.path = path self.size = int(size) def human_size(s): s = float(s) o = 0 while s > 1000: s /= 1000 o += 1 return str(round(s,1))+('B ','KB','MB','GB')[o] def prettyprint(f): print (' %s:%s' % (f.host, os.path.join(f.path, f))).ljust(80),\ human_size(f.size).rjust(8) def main(host=None): db = MythDB() be = MythBE() unfiltered = [] kwargs = {} if host: hosts = [host] kwargs['hostname'] = host else: with db as c: c.execute("""SELECT hostname FROM settings WHERE value='BackendServerIP'""") hosts = [r[0] for r in c.fetchall()] for host in hosts: for sg in db.getStorageGroup(): if sg.groupname in ('Videos','Banners','Coverart',\ 'Fanart','Screenshots','Trailers'): continue try: dirs,files,sizes = be.getSGList(host, sg.groupname, sg.dirname) for f,s in zip(files,sizes): newfile = File(host, sg.groupname, sg.dirname, f, s) if newfile not in unfiltered: unfiltered.append(newfile) except: pass recs = list(db.searchRecorded(**kwargs)) zerorecs = [] orphvids = [] for rec in list(recs): if rec.basename in unfiltered: recs.remove(rec) i = unfiltered.index(rec.basename) f = unfiltered.pop(i) if f.size < 1024: zerorecs.append(rec) name = rec.basename.rsplit('.',1)[0] for f in list(unfiltered): if name in f: unfiltered.remove(f) for f in list(unfiltered): if not (f.endswith('.mpg') or f.endswith('.nuv')): continue orphvids.append(f) unfiltered.remove(f) orphimgs = [] for f in list(unfiltered): if not f.endswith('.png'): continue orphimgs.append(f) unfiltered.remove(f) dbbackup = [] for f in list(unfiltered): if 'sql' not in f: continue dbbackup.append(f) unfiltered.remove(f) if len(recs): print "Recordings with missing files" for rec in recs: if rec.subtitle: print (' %s - %s' % (rec.title, rec.subtitle)).ljust(60), else: print (' %s' % rec.title).ljust(60), print rec.basename if len(zerorecs): print "\nZero byte recordings" for rec in zerorecs: if rec.subtitle: print (' %s - %s' % (rec.title, rec.subtitle)).ljust(40), else: print (' %s' % rec.title).ljust(40), print rec.basename if len(orphvids): print "\nOrphaned video files" for f in sorted(orphvids, key=lambda x: x.path): # os.unlink(os.path.join(f.path,f)) prettyprint(f) size = sum([f.size for f in orphvids]) print 'Total:'.rjust(80),human_size(size).rjust(8) if len(orphimgs): print "\nOrphaned snapshots" for f in sorted(orphimgs, key=lambda x: x.path): prettyprint(f) size = sum([f.size for f in orphimgs]) print 'Total:'.rjust(80),human_size(size).rjust(8) if len(dbbackup): print "\nDatabase backups" for f in sorted(dbbackup, key=lambda x: x.path): prettyprint(f) size = sum([f.size for f in dbbackup]) print 'Total:'.rjust(80),human_size(size).rjust(8) if len(unfiltered): print "\nOther files" for f in sorted(unfiltered, key=lambda x: x.path): prettyprint(f) size = sum([f.size for f in unfiltered]) print 'Total:'.rjust(80),human_size(size).rjust(8) if __name__ == '__main__': if len(sys.argv) == 2: main(sys.argv[1]) else: main()