annotate unixSoft/bin/sednames.py @ 161:668268f29a88

Merge
author Augie Fackler <durin42@gmail.com>
date Tue, 24 Nov 2009 15:20:07 -0600
parents 91dbdbea15e5
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
1 #!/usr/bin/env python
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
2
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
3 from itertools import imap as map
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
4 from itertools import izip as zip
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
5
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
6 import re
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
7 whitespace_chars = {
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
8 '\a': r'\a',
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
9 '\b': r'\b',
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
10 '\t': r'\t',
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
11 '\n': r'\n',
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
12 '\v': r'\v',
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
13 '\f': r'\f',
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
14 '\r': r'\r',
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
15 }
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
16 whitespace_chars_exp = re.compile('[' + ''.join(whitespace_chars) + ']')
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
17 chars_to_escape = dict(zip(map(chr, xrange(0x00, 0x20)), ('\\' + ch for ch in map(chr, xrange(0x00, 0x20)))))
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
18 for ch in '{}' "'" '"' '$*?':
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
19 chars_to_escape[ch] = '\\' + ch
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
20 for ch in whitespace_chars:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
21 del chars_to_escape[ch] # Let whitespace_chars handle these.
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
22 chars_to_escape_exp = re.compile('[][\\' + ''.join(chars_to_escape) + ']')
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
23 chars_to_escape['['] = '\['
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
24 chars_to_escape[']'] = '\]'
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
25 chars_to_escape['\\'] = '\\\\'
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
26 minimal_chars_to_escape_exp = re.compile("[\\']")
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
27
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
28 def quote_argument(arg):
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
29 count = 0
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
30 match = chars_to_escape_exp.search(arg)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
31 while match:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
32 count += 1
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
33 match = chars_to_escape_exp.search(arg, match.end())
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
34 else:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
35 del match
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
36
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
37 if count > 2:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
38 arg = "'" + re.sub(minimal_chars_to_escape_exp, lambda match: '\\' + match.group(0), arg) + "'"
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
39 else:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
40 arg = re.sub(chars_to_escape_exp, lambda match: chars_to_escape[match.group(0)], arg)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
41
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
42 arg = re.sub(whitespace_chars_exp, lambda match: whitespace_chars[match.group(0)], arg)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
43 return arg
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
44
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
45 def custom_rename(option, opt_str, value, parser):
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
46 for i, arg in enumerate(parser.rargs):
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
47 if arg == ';':
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
48 break
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
49 parser.values.ensure_value('custom_rename', parser.rargs[:i])
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
50 del parser.rargs[:i + 1]
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
51
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
52 import optparse
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
53 parser = optparse.OptionParser(description="This program batch-renames files, optionally using a VCS (such as svn, hg, or bzr) or other external program to do the renaming. You specify the rename operations using sed commands, which you specify using the -e option.")
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
54 parser.add_option('-e', '--program', action='append', default=[''])
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
55 parser.add_option('--vcs', metavar='VCS', help='Version-control system with which to rename files, using <VCS> mv <SRC> <DST>; overridden by --custom-rename')
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
56 parser.add_option('--custom-rename', help='Custom command to rename the file (e.g., hg mv); works like find(1) -exec (but with two {}, which are src and dst in that order), or you can use {SRC} and {DST}, or you can omit {...} entirely in which case src and dst will be appended in that order', action='callback', type=None, callback=custom_rename, default=None)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
57 parser.add_option('-q', '--quiet', action='store_true', default=False)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
58 opts, args = parser.parse_args()
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
59
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
60 try:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
61 custom_rename = opts.custom_rename
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
62 except AttributeError:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
63 try:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
64 custom_rename = [opts.vcs, 'mv']
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
65 except AttributeError:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
66 custom_rename = None
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
67
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
68 def prefix_with_dash_e(seq):
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
69 for arg in seq:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
70 yield '-e'
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
71 yield arg
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
72
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
73 import subprocess
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
74 sed = subprocess.Popen(['sed', '-El'] + list(prefix_with_dash_e(opts.program)), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
75
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
76 import os, sys
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
77 for src in args:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
78 sed.stdin.write(src + '\n')
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
79 sed.stdin.flush()
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
80 dst = sed.stdout.readline().rstrip('\n')
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
81 if src == dst:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
82 if not opts.quiet:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
83 print >>sys.stderr, 'sed program did not transform %r - skipping' % (src,)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
84 else:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
85 if custom_rename:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
86 src_and_dst = [src, dst]
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
87 rename_cmd = list(custom_rename)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
88 for i, arg in enumerate(rename_cmd):
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
89 if arg == '{SRC}':
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
90 rename_cmd[i] = src
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
91 elif arg == '{DST}':
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
92 rename_cmd[i] = dst
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
93 elif arg == '{}':
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
94 try:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
95 rename_cmd[i] = src_and_dst.pop(0)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
96 except IndexError:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
97 sys.exit('Too many {} arguments in custom rename command %r' % (custom_rename,))
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
98 else:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
99 rename_cmd += src_and_dst
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
100
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
101 if not opts.quiet:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
102 print >>sys.stderr, ' '.join(map(quote_argument, rename_cmd))
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
103 subprocess.check_call(rename_cmd)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
104 else:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
105 if not opts.quiet:
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
106 print >>sys.stderr, 'Renaming %r to %r' % (src, dst)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
107 os.rename(src, dst)
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
108
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
109 sed.stdin.close()
91dbdbea15e5 Merge in uncommitted changes.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
110 sys.exit(sed.wait())