1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#!/usr/bin/env python3
from __future__ import absolute_import, print_function, unicode_literals
import argparse
import hashlib
import os
import sys
from string import Template
def hashfile(hasher, fp, bs=2**16):
h = hasher()
buf = fp.read(bs)
while len(buf):
h.update(buf)
buf = fp.read(bs)
return h
def rename(fpath, mask, algorithm, abbrev=None, out=sys.stdout, err=sys.stderr):
print("Renaming with mask: %s" % args.mask, file=out)
if not os.path.exists(fpath):
print("File %s does not exists." % fpath, file=err)
else:
with open(fpath, 'rb') as fp:
hasher = getattr(hashlib, algorithm)
hsh = hashfile(hasher, fp).hexdigest()
if abbrev:
hsh = hsh[0:abbrev]
ext = os.path.splitext(fpath)[1][1:]
name = mask.substitute(hash=hsh, ext=ext)
dest = os.path.join(os.path.dirname(fpath), name)
if os.path.basename(fpath) == name:
print("OK %s" % name, file=out)
else:
print("`%s' -> `%s'" % (fpath, dest), file=out)
if os.path.exists(dest):
print("Destination %s already exists." % dest, file=err)
elif not args.pretend:
os.rename(fpath, dest)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="Rename files based on their content.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
def abbrev(arg):
arg = int(arg)
if arg == 0:
return None
if arg < 4:
raise argparse.ArgumentTypeError("You should use at least 4 digits.")
return arg
parser.add_argument('files', metavar='FILE', nargs='+',
help="files to rename")
parser.add_argument('-m', '--mask',
help="file destination mask", default='${hash}.${ext}')
parser.add_argument('-p', '--pretend', action='store_true',
help="do not rename, just print")
parser.add_argument('-a', '--algorithm',
help="hash algorithm", choices=hashlib.algorithms_available, default='sha1')
parser.add_argument('-b', '--abbrev', metavar='N', type=abbrev,
help="use the first N digits", default=None)
args = parser.parse_args()
for fpath in args.files:
rename(fpath, Template(args.mask), args.algorithm, args.abbrev)
|