-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathedmv
executable file
·148 lines (114 loc) · 4.37 KB
/
edmv
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
# From <https://github.com/casey/edmv/> (actually <https://github.com/casey/local/blob/master/bin/edmv>).
# Copy of the README:
# A small tool for bulk-renaming files using the editor of your choice.
#
# Demo here: http://youtu.be/EzhbTEh-7Fk
#
# WARNING: May delete everything on your computer. Read the source code, then the LICENSE file, and then don't sue me.
#
# Use it like this:
#
# edmv foo bar baz
#
# Or like this:
#
# emdv *
#
# It will invoke your editor on a list of the files provided, in this case foo, bar, and baz. Once you're done editing the filenames it will try to rename them to match any changes that you've made. Be careful!
#
# You can tell edmv which editor to use by:
#
# Supplying an argument to the --editor flag
# Setting the $EDMV_EDITOR environment variable
# Setting the $EDITOR environment variable
# Not doing anything, in which case edmv will default to vi, just as Bill Joy intended
#
# If you would like to use an OS X application for your editor, for example Sublime Text 2, it is speculated that you could put something like the following in your shell rc file: export EDMV_EDITOR='open -Wa "Sublime Text 2"'.
#
# If you use MacPorts, you can install edmv with port install edmv.
"""
Rename files with your favorite editor. (Or whatever happens to be in $EDMV_EDITOR or $EDITOR.)
"""
import argparse, os, shutil, subprocess, sys, tempfile
def die(msg='', code=1):
sys.stderr.write("edmv: %s\n" % msg)
sys.stderr.flush()
exit(code)
def dups(l):
return [x for x in l if l.count(x) > 1]
parser = argparse.ArgumentParser(prog="edmv", description=__doc__)
parser.add_argument("src_files",
metavar="FILE",
nargs="+",
help="The file(s) to rename.")
parser.add_argument("--ln",
action="store_true",
default=False,
help="Create symlinks instead of renaming.")
parser.add_argument("-n", "--no",
action="store_true",
default=False,
help="Dry run. Prints what would happen but doesn't move files.")
parser.add_argument("-f", "--force",
action="store_true",
default=False,
help="Allow overwriting existing files.")
parser.add_argument("-e", "--editor",
type=str,
default=None,
help="Specify your editor explicitly, instead of using $EDMV_EDITOR or $EDITOR.")
parser.add_argument('--version', action='version', version='%(prog)s 0.1.0')
args = parser.parse_args()
src_files = args.src_files
if '-' in src_files:
i = src_files.index('-')
stdin_files = sys.stdin.read().splitlines()
src_files[i:i+1] = stdin_files
file_count = len(src_files)
src_file_dups = dups(src_files)
if src_file_dups:
die("duplicates files: %s" % (", ".join(src_file_dups)))
for f in src_files:
if not os.path.exists(f):
die("file does not exist: %s" % f)
editor = args.editor or os.environ.get("EDMV_EDITOR") or os.environ.get('EDITOR') or 'vi'
with tempfile.NamedTemporaryFile(prefix="edmv-", delete=False) as f:
tmpfile = f.name
f.write(("\n".join(src_files) + "\n").encode('utf-8'))
code = subprocess.call("%s %s" % (editor, tmpfile), shell=True)
if code != 0:
die("call to %s failed with return code %s" % (editor, code))
with open(tmpfile) as f:
dst_files = f.read().splitlines()
os.remove(tmpfile)
if len(dst_files) != file_count:
die("line count bad: should be %s, actually %s" % (file_count, len(dst_files)))
dst_file_dups = dups(dst_files)
if dst_file_dups:
die("duplicate files: %s" % (", ".join(dst_file_dups)))
pairs = list(zip(src_files, dst_files))
if not args.force:
for src, dst in pairs:
if src != dst and os.path.exists(dst):
die("destination file exists, use -f to overwrite: %s" % dst)
for f in dst_files:
dirname = os.path.dirname(os.path.abspath(f))
if not os.path.exists(dirname):
die("destination directory does not exist: %s" % dirname)
unchanged = 0
for src, dst in pairs:
if not dst:
die("bad path: '%s'" % dst)
if src == dst:
unchanged += 1
continue
sys.stderr.write("%s -> %s\n" % (src, dst))
if args.no:
pass
elif args.ln:
subprocess.call(f"ln -s \"{src}\" \"{dst}\"", shell=True)
else:
shutil.move(src, dst)
if unchanged:
sys.stderr.write("(%s files unchanged)\n" % unchanged)