#!/usr/bin/env python #================================================================ # oldfiles.py: Show files in reverse chron. order by mod. time. # For documentation in "literate programming" style, see: # http://www.nmt.edu/help/lang/python/examples/pathinfo/ #---------------------------------------------------------------- SCRIPT_NAME = "oldfiles.py" EXTERNAL_VERSION = "1.1" #================================================================ # Imports #---------------------------------------------------------------- import sys, os import pathinfo # - - - - - m a i n - - - - - def main(): """Main program.""" print "=== %s %s ===" % (SCRIPT_NAME, EXTERNAL_VERSION) #-- 1 -- # [ if sys.argv[1:] is empty -> # dirList := [ "." ] # else -> # dirList := sys.argv[1:] ] dirList = sys.argv[1:] if len(dirList) == 0: dirList = [ "." ] #-- 2 -- # [ sys.stdout +:= reports listing files below each # directory named in dirList, with files in reverse # chronological order by modification time ] for dirName in dirList: #-- 2 body -- # [ dirName is a string -> # sys.stdout +:= a report listing the files below # directory (dirName), with files in reverse # chronological order by modification time ] report ( dirName ) # - - - r e p o r t - - - def report ( dirName ): """Generate the report for one directory subtree. [ dirName is a string -> sys.stdout +:= a report listing the files below directory (dirName), with files in reverse chronological order by modification time ] """ #-- 1 - # [ basePath := dirName's absolute path name # sys.stdout +:= report heading showing dirName's real # absolute path ] basePath = os.path.abspath ( dirName ) print "\n === %s ===" % os.path.realpath ( dirName ) #-- 2 -- # [ oldReport := an OldReport object describing all the # accessible files in directory tree (dirName) ] oldReport = OldReport ( basePath ) #-- 3 -- # [ oldReport is an OldReport object -> # sys.stdout +:= lines describing files in oldReport # in chronological order by modification time ] for oldInfo in oldReport.genFiles(): print oldInfo #================================================================ # Functions and classes #---------------------------------------------------------------- # - - - - - c l a s s O l d I n f o - - - - - class OldInfo(pathinfo.PathInfo): """Represents information about one file; sorts by mod time. """ # - - - O l d I n f o . _ _ i n i t _ _ - - - def __init__ ( self, path, basePath ): """Constructor for OldInfo.""" #-- 1 -- pathinfo.PathInfo.__init__ ( self, path ) #-- 2 -- self.__basePath = basePath # - - - O l d I n f o . _ _ c m p _ _ - - - def __cmp__ ( self, other ): """Compare two OldInfo objects. [ other is an OldInfo object -> if self should precede other -> return a negative number else if self should follow other -> return a positive number else -> return 0 ] """ return cmp ( other.modEpoch, self.modEpoch ) # - - - O l d I n f o . _ _ s t r _ _ - - - def __str__ ( self ): """Format an OldInfo object for printing.""" #-- 1 -- # [ if self represents a directory -> # suffix := "/" # else -> # suffix := "" ] if self.isDir(): suffix = "/" else: suffix = "" #-- 2 -- # [ self.__basePath is the absolute path of a directory # above self.path -> # relPath := path to self.path relative to # self.__basePath ] absPath = os.path.abspath ( self.path ) relPath = absPath [ len(self.__basePath) + 1 : ] #-- 3 -- if relPath == "": relPath = "." suffix = "" #-- 4 -- return ( "%s %10s %s%s" % (self.modTime(), self.size, relPath, suffix) ) # - - - - - c l a s s O l d R e p o r t - - - - - class OldReport: """Holds the old-files report. Exports: OldReport ( dir ): [ dir is a string -> if dir names a directory to which we have access -> return an OldReport object describing all the accessible files in that directory's subtree else -> raise OSError ] .genFiles(): [ generate a sequence of OldInfo objects representing the files in self, in reverse chronological order by modification timestamp ] Class invariants: .__oldList: [ a list of information on all the files in self as OldInfo objects, sorted ] """ # - - - O l d R e p o r t . _ _ i n i t _ _ - - - def __init__ ( self, dir ): """Constructor for the OldReport class.""" #-- 1 -- self.__oldList = [] #-- 2 -- # [ dir is a string -> # self.__oldList := self.__oldList with OldInfo # objects added representing every accessible # file in the subtree named by dir ] os.path.walk ( dir, self.__visitor, dir ) #-- 3 -- # [ self.__oldList := self.__oldList, sorted ] self.__oldList.sort() # - - - O l d R e p o r t . _ _ v i s i t o r - - - def __visitor ( self, basePath, dirName, nameList ): """Visitor function for os.path.walk. [ (dirName is the name of a directory) and (nameList is a list of the names within that directory) -> self.__oldList := self.__oldList with BigInfo objects added representing the accessible ordinary files in nameList ] """ #-- 1 -- # [ self.__oldList := self.__oldList with an OldInfo # object added representing dirName ] try: dirInfo = OldInfo ( dirName, basePath ) self.__oldList.append ( dirInfo ) except OSError, detail: pass #-- 2 -- for fileName in nameList: #-- 2 body -- # [ if fileName names an accessible regular file -> # self.__oldList := self.__oldList with a new # OldInfo object representing fileName # else -> I ] #-- 2.1 -- # [ filePath := dirName + fileName ] filePath = os.path.join ( dirName, fileName ) #-- 2.2 -- # [ if filePath is an accessible path to a regular file -> # self.__oldList := self.__oldList + (an OldInfo # showing the status of filePath) # else -> I ] try: oldInfo = OldInfo ( filePath, basePath ) if oldInfo.isFile(): self.__oldList.append ( oldInfo ) except OSError, detail: pass # - - - O l d R e p o r t . g e n F i l e s - - - def genFiles ( self ): """Generate the OldInfo objects in self.__oldList.""" for oldInfo in self.__oldList: yield oldInfo raise StopIteration # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if __name__ == "__main__": main()