1
1
#!/usr/bin/env python3
2
2
3
- # Change the #! line occurring in Python scripts. The new interpreter
3
+ # Change the #! line (shebang) occurring in Python scripts. The new interpreter
4
4
# pathname must be given with a -i option.
5
5
#
6
6
# Command line arguments are files or directories to be processed.
10
10
# arguments).
11
11
# The original file is kept as a back-up (with a "~" attached to its name),
12
12
# -n flag can be used to disable this.
13
- #
13
+
14
+ # Sometimes you may find shebangs with flags such as `#! /usr/bin/env python -si`.
15
+ # Normally, pathfix overwrites the entire line, including the flags.
16
+ # To change interpreter and keep flags from the original shebang line, use -k.
17
+
18
+
14
19
# Undoubtedly you can do this using find and sed or perl, but this is
15
20
# a nice example of Python code that recurses down a directory tree
16
21
# and uses regular expressions. Also note several subtleties like
33
38
new_interpreter = None
34
39
preserve_timestamps = False
35
40
create_backup = True
41
+ keep_flags = False
36
42
37
43
38
44
def main ():
39
45
global new_interpreter
40
46
global preserve_timestamps
41
47
global create_backup
42
- usage = ('usage: %s -i /interpreter -p -n file-or-directory ...\n ' %
48
+ global keep_flags
49
+
50
+ usage = ('usage: %s -i /interpreter -p -n -k file-or-directory ...\n ' %
43
51
sys .argv [0 ])
44
52
try :
45
- opts , args = getopt .getopt (sys .argv [1 :], 'i:pn ' )
53
+ opts , args = getopt .getopt (sys .argv [1 :], 'i:kpn ' )
46
54
except getopt .error as msg :
47
55
err (str (msg ) + '\n ' )
48
56
err (usage )
@@ -54,6 +62,8 @@ def main():
54
62
preserve_timestamps = True
55
63
if o == '-n' :
56
64
create_backup = False
65
+ if o == '-k' :
66
+ keep_flags = True
57
67
if not new_interpreter or not new_interpreter .startswith (b'/' ) or \
58
68
not args :
59
69
err ('-i option or file-or-directory missing\n ' )
@@ -70,10 +80,14 @@ def main():
70
80
if fix (arg ): bad = 1
71
81
sys .exit (bad )
72
82
83
+
73
84
ispythonprog = re .compile (r'^[a-zA-Z0-9_]+\.py$' )
85
+
86
+
74
87
def ispython (name ):
75
88
return bool (ispythonprog .match (name ))
76
89
90
+
77
91
def recursedown (dirname ):
78
92
dbg ('recursedown(%r)\n ' % (dirname ,))
79
93
bad = 0
@@ -96,6 +110,7 @@ def recursedown(dirname):
96
110
if recursedown (fullname ): bad = 1
97
111
return bad
98
112
113
+
99
114
def fix (filename ):
100
115
## dbg('fix(%r)\n' % (filename,))
101
116
try :
@@ -164,12 +179,26 @@ def fix(filename):
164
179
# Return success
165
180
return 0
166
181
182
+
183
+ def parse_shebang (shebangline ):
184
+ shebangline = shebangline .rstrip (b'\n ' )
185
+ start = shebangline .find (b' -' )
186
+ if start == - 1 :
187
+ return b''
188
+ return shebangline [start :]
189
+
190
+
167
191
def fixline (line ):
168
192
if not line .startswith (b'#!' ):
169
193
return line
194
+
170
195
if b"python" not in line :
171
196
return line
172
- return b'#! ' + new_interpreter + b'\n '
197
+ flags = b''
198
+ if keep_flags :
199
+ flags = parse_shebang (line )
200
+ return b'#! ' + new_interpreter + flags + b'\n '
201
+
173
202
174
203
if __name__ == '__main__' :
175
204
main ()
0 commit comments