-
Notifications
You must be signed in to change notification settings - Fork 0
/
br
executable file
·90 lines (73 loc) · 3.03 KB
/
br
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
#!/usr/bin/env python
# mostly copied from ranger's bulkrename command (https://github.com/ranger/ranger/blob/master/ranger/config/commands.py#L1114)
# and from ranger's shell_escape util (https://github.com/ranger/ranger/blob/master/ranger/ext/shell_escape.py)
import os
import sys
import tempfile
import subprocess
META_CHARS = (' ', "'", '"', '`', '&', '|', ';', '#',
'$', '!', '(', ')', '[', ']', '<', '>', '\t')
UNESCAPABLE = set(map(chr, list(range(9)) + list(range(10, 32)) + list(range(127, 256))))
META_DICT = dict([(mc, '\\' + mc) for mc in META_CHARS])
def shell_quote(string):
"""Escapes by quoting"""
return "'" + str(string).replace("'", "'\\''") + "'"
def shell_escape(arg):
"""Escapes by adding backslashes"""
arg = str(arg)
if UNESCAPABLE & set(arg):
return shell_quote(arg)
arg = arg.replace('\\', '\\\\') # make sure this comes at the start
for key, value in META_DICT.items():
arg = arg.replace(key, value)
return arg
# throw help message if no paths were passed
if len(sys.argv) == 1:
print(f"Usage: {os.path.basename(sys.argv[0])} [directory|file]")
quit()
# get files and editor
filenames = sys.argv[1:]
editor = os.environ.get('EDITOR','vim')
# write list of files into tmp file
tmp_filelist = tempfile.NamedTemporaryFile(delete=False)
tmp_filelist.write("\n".join(filenames).encode("utf-8"))
tmp_filename = tmp_filelist.name
tmp_filelist.close()
# open tmp file in editor
subprocess.call([editor, tmp_filename ])
# get new file names and delete tmp file
tmp_listfile = open(tmp_filename , 'r')
new_filenames = tmp_listfile.read().split("\n")
tmp_listfile.close()
os.unlink(tmp_filename)
# check if all new names are the same as old names
if all(a == b for a, b in zip(filenames, new_filenames)):
print("No renaming to be done.")
quit()
# create tmp script file for renaming review
cmdfile = tempfile.NamedTemporaryFile()
script_lines = []
script_lines.append("# This file will be executed when you close the editor.")
script_lines.append("# Please double-check everything, clear the file to abort.")
new_dirs = []
# make sure the number of new files equals the number of old files
if len(filenames) != (len(new_filenames) - 1):
print("Number of new files does not match the number of old files.")
quit()
# add commands to rename files and create new folders if necessary
for old, new in zip(filenames, new_filenames):
if old != new:
basepath, _ = os.path.split(os.path.abspath(new))
if (basepath is not None) and (basepath not in new_dirs) and (not os.path.isdir(basepath)):
script_lines.append(f"mkdir -vp -- {shell_escape(basepath)}")
new_dirs.append(basepath)
script_lines.append(f"mv -vi -- {shell_escape(old)} {shell_escape(new)}")
# write commands to file
script_content = "\n".join(script_lines) + "\n"
cmdfile.write(script_content.encode("utf-8"))
cmdfile.flush()
# open cmd file in editor
subprocess.call([editor, cmdfile.name])
# rename files
subprocess.call(['/bin/sh', cmdfile.name])
cmdfile.close()