view unixSoft/bin/sednames.py @ 307:e37b00236907

zshrc: work around my shell function that turns on utf8 in screen The zsh built in which was getting confused by the function, and always claimed screen was installed. I'm finally running into machines with tmux but not screen, so I noticed.
author Augie Fackler <raf@durin42.com>
date Sat, 19 Jan 2013 19:29:58 -0600
parents 91dbdbea15e5
children
line wrap: on
line source

#!/usr/bin/env python

from itertools import imap as map
from itertools import izip as zip

import re
whitespace_chars = {
	'\a': r'\a',
	'\b': r'\b',
	'\t': r'\t',
	'\n': r'\n',
	'\v': r'\v',
	'\f': r'\f',
	'\r': r'\r',
}
whitespace_chars_exp = re.compile('[' + ''.join(whitespace_chars) + ']')
chars_to_escape = dict(zip(map(chr, xrange(0x00, 0x20)), ('\\' + ch for ch in map(chr, xrange(0x00, 0x20)))))
for ch in '{}' "'" '"' '$*?':
	chars_to_escape[ch] = '\\' + ch
for ch in whitespace_chars:
	del chars_to_escape[ch] # Let whitespace_chars handle these.
chars_to_escape_exp = re.compile('[][\\' + ''.join(chars_to_escape) + ']')
chars_to_escape['['] = '\['
chars_to_escape[']'] = '\]'
chars_to_escape['\\'] = '\\\\'
minimal_chars_to_escape_exp = re.compile("[\\']")

def quote_argument(arg):
	count = 0
	match = chars_to_escape_exp.search(arg)
	while match:
		count += 1
		match = chars_to_escape_exp.search(arg, match.end())
	else:
		del match

	if count > 2:
		arg = "'" + re.sub(minimal_chars_to_escape_exp, lambda match: '\\' + match.group(0), arg) + "'"
	else:
		arg = re.sub(chars_to_escape_exp, lambda match: chars_to_escape[match.group(0)], arg)

	arg = re.sub(whitespace_chars_exp, lambda match: whitespace_chars[match.group(0)], arg)
	return arg

def custom_rename(option, opt_str, value, parser):
	for i, arg in enumerate(parser.rargs):
		if arg == ';':
			break
	parser.values.ensure_value('custom_rename', parser.rargs[:i])
	del parser.rargs[:i + 1]

import optparse
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.")
parser.add_option('-e', '--program', action='append', default=[''])
parser.add_option('--vcs', metavar='VCS', help='Version-control system with which to rename files, using <VCS> mv <SRC> <DST>; overridden by          --custom-rename')
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)
parser.add_option('-q', '--quiet', action='store_true', default=False)
opts, args = parser.parse_args()

try:
	custom_rename = opts.custom_rename
except AttributeError:
	try:
		custom_rename = [opts.vcs, 'mv']
	except AttributeError:
		custom_rename = None

def prefix_with_dash_e(seq):
	for arg in seq:
		yield '-e'
		yield arg

import subprocess
sed = subprocess.Popen(['sed', '-El'] + list(prefix_with_dash_e(opts.program)), stdin=subprocess.PIPE, stdout=subprocess.PIPE)

import os, sys
for src in args:
	sed.stdin.write(src + '\n')
	sed.stdin.flush()
	dst = sed.stdout.readline().rstrip('\n')
	if src == dst:
		if not opts.quiet:
			print >>sys.stderr, 'sed program did not transform %r - skipping' % (src,)
	else:
		if custom_rename:
			src_and_dst = [src, dst]
			rename_cmd = list(custom_rename)
			for i, arg in enumerate(rename_cmd):
				if arg == '{SRC}':
					rename_cmd[i] = src
				elif arg == '{DST}':
					rename_cmd[i] = dst
				elif arg == '{}':
					try:
						rename_cmd[i] = src_and_dst.pop(0)
					except IndexError:
						sys.exit('Too many {} arguments in custom rename command %r' % (custom_rename,))
			else:
				rename_cmd += src_and_dst

			if not opts.quiet:
				print >>sys.stderr, ' '.join(map(quote_argument, rename_cmd))
			subprocess.check_call(rename_cmd)
		else:
			if not opts.quiet:
				print >>sys.stderr, 'Renaming %r to %r' % (src, dst)
			os.rename(src, dst)

sed.stdin.close()
sys.exit(sed.wait())