I have written a (useful?) script to find all packages which have not be used for a long time and reports this to the user (i.e., some package is installed but none of its files have been accessed in 60 days). Would this be useful? Is there some other forum where I should post this?
I have attached the script for consideration. The only requirements are ruby-1.8 and grep-dctrl. -Dale Hawkins
#!/usr/bin/ruby require 'pathname' require 'getoptlong' def usage $stderr.puts "usage: #{$0} [ -v ]* [ -r ] [ -d days(60) ] <pkg_name> [ ... ]" exit 1 end days = 60 verbose = 0 recursive = false opts = GetoptLong.new(["--days", "-d", GetoptLong::REQUIRED_ARGUMENT], ["--verbose", "-v", GetoptLong::NO_ARGUMENT], ["--recursive", "-r", GetoptLong::NO_ARGUMENT], ["--help", "-h", GetoptLong::NO_ARGUMENT]) opts.each {|opt,val| case opt when "--days" then days = val when "--verbose" then verbose += 1 # when "--recursive" then recursive = true else usage end } if days.to_i == 0 $stderr.puts "illegal value given for days: #{days}" end days = days.to_i if ARGV.empty? packages = IO.popen('grep-status -FStatus -sPackage -n "install ok installed"').readlines else packages = ARGV end class Pathname @@secondsPerDay = 60 * 60 * 24 def parentInArray(paths) paths.any? { | p | fnmatch(p) } end def lastAccessed(t = Time.now) ((t - self.atime)/@@secondsPerDay).to_i end end class Package @@filesToIgnore = [ '/usr/lib/menu/*', '/usr/share/applications/*', '/usr/share/man/*', '/usr/share/pixmaps/*', '/usr/share/mime-info/*', '/usr/lib/mime/packages/*', '/usr/share/doc-base/*', ] @@docDirs = [ '/usr/share/doc/*', ] @@binaryDirs = [ '/lib/*', '/usr/lib/*', '/bin/*', '/usr/bin/*', ] def initialize(name) @name = name end def getFiles if not defined? @files @files = IO.popen("grep-dctrl -FStatus ' installed' /var/lib/dpkg/status | grep-dctrl -PX -n -s Package [EMAIL PROTECTED]").collect { | pkg | IO.popen("dpkg --listfiles #{pkg}").collect { | fn | fn.chomp! if fn.empty? false else p = Pathname.new(fn.chomp) end }.select { | p | p && (p.file? && (! p.parentInArray(@@filesToIgnore))) } }.flatten end if @files.empty? raise "No regular files found (or package not installed)" end @files end def docFiles if not defined? @docFiles @docFiles = getFiles.select { | p | p.parentInArray(@@docDirs) }.sort {|x,y| y.atime <=> x.atime } end @docFiles end def binaryFiles if not defined? @binFiles @binFiles = getFiles.select { | p | p.parentInArray(@@binaryDirs) }.sort {|x,y| y.atime <=> x.atime } end @binFiles end def lastDocAccess if docFiles.empty? raise "No document files" else docFiles[0].lastAccessed end end def showlastDocumentAccess(number = 1) if docFiles.empty? raise "No doc files" else access_times = (0...([number, docFiles.size].min)).collect { | n | "#{docFiles[n]} was last accessed #{docFiles[n].lastAccessed} days ago" } end end def lastBinaryAccess if binaryFiles.empty? raise "No binary files" else binaryFiles[0].lastAccessed end end def showlastBinaryAccess(number = 1) if binaryFiles.empty? raise "No binary files" else access_times = (0...([number, binaryFiles.size].min)).collect { | n | "#{binaryFiles[n]} was last accessed #{binaryFiles[n].lastAccessed} days ago" } end end def getWhatDeps IO.popen("grep-status -n -s Package -FDepends -e [EMAIL PROTECTED]").readlines end end packages.each { | pn | pn.chomp! next if pn.empty? if verbose > 0 puts "=============== #{pn} ===============" end success = false p = Package.new(pn) binDays = 10000 begin binDays = p.lastBinaryAccess if verbose > 1 puts p.showlastBinaryAccess(10).collect { | s | " " + s } end success = true rescue if verbose > 0 $stderr.puts $! end end docDays = 10000 begin docDays = p.lastDocAccess if verbose > 1 puts p.showlastDocumentAccess(10).collect { | s | " " + s } end success = true rescue if verbose > 0 $stderr.puts $! end end if success if [binDays, docDays].min > days puts "Recommend #{pn} for removal" if recursive puts p.getWhatDeps end else if verbose > 0 puts "Keeping #{pn}" end end end }