Home | History | Annotate | Download | only in scripts
      1 #! /usr/bin/env python

      2 
      3 """Python utility to print MD5 checksums of argument files.
      4 """
      5 
      6 
      7 bufsize = 8096
      8 fnfilter = None
      9 rmode = 'rb'
     10 
     11 usage = """
     12 usage: sum5 [-b] [-t] [-l] [-s bufsize] [file ...]
     13 -b        : read files in binary mode (default)
     14 -t        : read files in text mode (you almost certainly don't want this!)
     15 -l        : print last pathname component only
     16 -s bufsize: read buffer size (default %d)
     17 file ...  : files to sum; '-' or no files means stdin
     18 """ % bufsize
     19 
     20 import sys
     21 import os
     22 import getopt
     23 import md5
     24 
     25 def sum(*files):
     26     sts = 0
     27     if files and isinstance(files[-1], file):
     28         out, files = files[-1], files[:-1]
     29     else:
     30         out = sys.stdout
     31     if len(files) == 1 and not isinstance(files[0], str):
     32         files = files[0]
     33     for f in files:
     34         if isinstance(f, str):
     35             if f == '-':
     36                 sts = printsumfp(sys.stdin, '<stdin>', out) or sts
     37             else:
     38                 sts = printsum(f, out) or sts
     39         else:
     40             sts = sum(f, out) or sts
     41     return sts
     42 
     43 def printsum(filename, out=sys.stdout):
     44     try:
     45         fp = open(filename, rmode)
     46     except IOError, msg:
     47         sys.stderr.write('%s: Can\'t open: %s\n' % (filename, msg))
     48         return 1
     49     if fnfilter:
     50         filename = fnfilter(filename)
     51     sts = printsumfp(fp, filename, out)
     52     fp.close()
     53     return sts
     54 
     55 def printsumfp(fp, filename, out=sys.stdout):
     56     m = md5.new()
     57     try:
     58         while 1:
     59             data = fp.read(bufsize)
     60             if not data:
     61                 break
     62             m.update(data)
     63     except IOError, msg:
     64         sys.stderr.write('%s: I/O error: %s\n' % (filename, msg))
     65         return 1
     66     out.write('%s %s\n' % (m.hexdigest(), filename))
     67     return 0
     68 
     69 def main(args = sys.argv[1:], out=sys.stdout):
     70     global fnfilter, rmode, bufsize
     71     try:
     72         opts, args = getopt.getopt(args, 'blts:')
     73     except getopt.error, msg:
     74         sys.stderr.write('%s: %s\n%s' % (sys.argv[0], msg, usage))
     75         return 2
     76     for o, a in opts:
     77         if o == '-l':
     78             fnfilter = os.path.basename
     79         elif o == '-b':
     80             rmode = 'rb'
     81         elif o == '-t':
     82             rmode = 'r'
     83         elif o == '-s':
     84             bufsize = int(a)
     85     if not args:
     86         args = ['-']
     87     return sum(args, out)
     88 
     89 if __name__ == '__main__' or __name__ == sys.argv[0]:
     90     sys.exit(main(sys.argv[1:], sys.stdout))
     91