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