Mercurial > dotfiles
comparison unixSoft/bin/sednames.py @ 1:91dbdbea15e5
Merge in uncommitted changes.
| author | Augie Fackler <durin42@gmail.com> |
|---|---|
| date | Wed, 26 Nov 2008 15:03:40 -0600 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:c30d68fbd368 | 1:91dbdbea15e5 |
|---|---|
| 1 #!/usr/bin/env python | |
| 2 | |
| 3 from itertools import imap as map | |
| 4 from itertools import izip as zip | |
| 5 | |
| 6 import re | |
| 7 whitespace_chars = { | |
| 8 '\a': r'\a', | |
| 9 '\b': r'\b', | |
| 10 '\t': r'\t', | |
| 11 '\n': r'\n', | |
| 12 '\v': r'\v', | |
| 13 '\f': r'\f', | |
| 14 '\r': r'\r', | |
| 15 } | |
| 16 whitespace_chars_exp = re.compile('[' + ''.join(whitespace_chars) + ']') | |
| 17 chars_to_escape = dict(zip(map(chr, xrange(0x00, 0x20)), ('\\' + ch for ch in map(chr, xrange(0x00, 0x20))))) | |
| 18 for ch in '{}' "'" '"' '$*?': | |
| 19 chars_to_escape[ch] = '\\' + ch | |
| 20 for ch in whitespace_chars: | |
| 21 del chars_to_escape[ch] # Let whitespace_chars handle these. | |
| 22 chars_to_escape_exp = re.compile('[][\\' + ''.join(chars_to_escape) + ']') | |
| 23 chars_to_escape['['] = '\[' | |
| 24 chars_to_escape[']'] = '\]' | |
| 25 chars_to_escape['\\'] = '\\\\' | |
| 26 minimal_chars_to_escape_exp = re.compile("[\\']") | |
| 27 | |
| 28 def quote_argument(arg): | |
| 29 count = 0 | |
| 30 match = chars_to_escape_exp.search(arg) | |
| 31 while match: | |
| 32 count += 1 | |
| 33 match = chars_to_escape_exp.search(arg, match.end()) | |
| 34 else: | |
| 35 del match | |
| 36 | |
| 37 if count > 2: | |
| 38 arg = "'" + re.sub(minimal_chars_to_escape_exp, lambda match: '\\' + match.group(0), arg) + "'" | |
| 39 else: | |
| 40 arg = re.sub(chars_to_escape_exp, lambda match: chars_to_escape[match.group(0)], arg) | |
| 41 | |
| 42 arg = re.sub(whitespace_chars_exp, lambda match: whitespace_chars[match.group(0)], arg) | |
| 43 return arg | |
| 44 | |
| 45 def custom_rename(option, opt_str, value, parser): | |
| 46 for i, arg in enumerate(parser.rargs): | |
| 47 if arg == ';': | |
| 48 break | |
| 49 parser.values.ensure_value('custom_rename', parser.rargs[:i]) | |
| 50 del parser.rargs[:i + 1] | |
| 51 | |
| 52 import optparse | |
| 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.") | |
| 54 parser.add_option('-e', '--program', action='append', default=['']) | |
| 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') | |
| 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) | |
| 57 parser.add_option('-q', '--quiet', action='store_true', default=False) | |
| 58 opts, args = parser.parse_args() | |
| 59 | |
| 60 try: | |
| 61 custom_rename = opts.custom_rename | |
| 62 except AttributeError: | |
| 63 try: | |
| 64 custom_rename = [opts.vcs, 'mv'] | |
| 65 except AttributeError: | |
| 66 custom_rename = None | |
| 67 | |
| 68 def prefix_with_dash_e(seq): | |
| 69 for arg in seq: | |
| 70 yield '-e' | |
| 71 yield arg | |
| 72 | |
| 73 import subprocess | |
| 74 sed = subprocess.Popen(['sed', '-El'] + list(prefix_with_dash_e(opts.program)), stdin=subprocess.PIPE, stdout=subprocess.PIPE) | |
| 75 | |
| 76 import os, sys | |
| 77 for src in args: | |
| 78 sed.stdin.write(src + '\n') | |
| 79 sed.stdin.flush() | |
| 80 dst = sed.stdout.readline().rstrip('\n') | |
| 81 if src == dst: | |
| 82 if not opts.quiet: | |
| 83 print >>sys.stderr, 'sed program did not transform %r - skipping' % (src,) | |
| 84 else: | |
| 85 if custom_rename: | |
| 86 src_and_dst = [src, dst] | |
| 87 rename_cmd = list(custom_rename) | |
| 88 for i, arg in enumerate(rename_cmd): | |
| 89 if arg == '{SRC}': | |
| 90 rename_cmd[i] = src | |
| 91 elif arg == '{DST}': | |
| 92 rename_cmd[i] = dst | |
| 93 elif arg == '{}': | |
| 94 try: | |
| 95 rename_cmd[i] = src_and_dst.pop(0) | |
| 96 except IndexError: | |
| 97 sys.exit('Too many {} arguments in custom rename command %r' % (custom_rename,)) | |
| 98 else: | |
| 99 rename_cmd += src_and_dst | |
| 100 | |
| 101 if not opts.quiet: | |
| 102 print >>sys.stderr, ' '.join(map(quote_argument, rename_cmd)) | |
| 103 subprocess.check_call(rename_cmd) | |
| 104 else: | |
| 105 if not opts.quiet: | |
| 106 print >>sys.stderr, 'Renaming %r to %r' % (src, dst) | |
| 107 os.rename(src, dst) | |
| 108 | |
| 109 sed.stdin.close() | |
| 110 sys.exit(sed.wait()) |
