3
3
# written by Joshua Boudreau <[email protected] > 2022
4
4
5
5
import os
6
- import re
7
6
import argparse
8
- import re
7
+ import sys
9
8
10
9
11
10
def get_unique_name (root , name , taken_paths ):
@@ -33,11 +32,13 @@ def windows_allowed(c): return c not in windows_ill
33
32
return "" .join (map (lambda c : c if printable (c ) and windows_allowed (c ) else '_' , string ))
34
33
35
34
36
- def rename_mangled (paths , dry_run ):
35
+ def rename_mangled (paths , dry_run , recursive ):
37
36
taken_paths = []
37
+ change_count = 0
38
38
39
39
def rename_entries (root , entries , rootfd ):
40
40
changes = []
41
+ nonlocal change_count
41
42
for src in entries :
42
43
dst = legalize_name (src )
43
44
if dst != src :
@@ -46,6 +47,7 @@ def rename_entries(root, entries, rootfd):
46
47
print (f"'{ src .encode ('unicode_escape' ).decode ('utf-8' )} '" , '->' )
47
48
print (f"'{ dst .encode ('unicode_escape' ).decode ('utf-8' )} '" )
48
49
print ()
50
+ change_count += 1
49
51
if dry_run :
50
52
continue
51
53
try :
@@ -57,22 +59,35 @@ def rename_entries(root, entries, rootfd):
57
59
entries .remove (src )
58
60
entries .append (dst )
59
61
for path in paths :
60
- for root , dirs , files , rootfd in os .fwalk (path , topdown = True ):
61
- if '.zfs' in dirs :
62
- dirs .remove ('.zfs' )
63
- rename_entries (root , dirs , rootfd )
64
- rename_entries (root , files , rootfd )
62
+ if os .path .isdir (path ) and recursive :
63
+ for root , dirs , files , rootfd in os .fwalk (path , topdown = True ):
64
+ if '.zfs' in dirs :
65
+ dirs .remove ('.zfs' )
66
+ rename_entries (root , dirs , rootfd )
67
+ rename_entries (root , files , rootfd )
68
+ if os .path .exists (path ):
69
+ fullpath = os .path .realpath (path )
70
+ root = os .path .dirname (fullpath )
71
+ entries = [os .path .basename (fullpath )]
72
+ rootfd = os .open (root , os .O_RDONLY )
73
+ rename_entries (root , entries , rootfd )
74
+ return change_count
65
75
66
76
67
77
def main ():
68
- parser = argparse .ArgumentParser ()
69
- parser .add_argument ('roots' , type = str , nargs = '+' , metavar = 'ROOT_PATH' )
70
- # parser.add_argument('-d', '--dry-run', action='store_true', default=False)
78
+ parser = argparse .ArgumentParser (
79
+ description = 'Rename files and directories to play nice with Windows' )
80
+ parser .add_argument ('roots' , type = str , nargs = '+' , metavar = 'PATH' ,
81
+ help = 'Path(s) to rename' )
82
+ parser .add_argument ('-r' , '--recursive' , action = 'store_true' , default = False , help = 'Recurse into directories' )
71
83
args = parser .parse_args ()
72
- rename_mangled (args .roots , True ) # dry run
73
- response = input ("is this okay? [y/N]: " )
84
+ mangled_count = rename_mangled (args .roots , True , args .recursive ) # dry run
85
+ print (f"Found { mangled_count } invalid paths" )
86
+ if mangled_count == 0 :
87
+ sys .exit ()
88
+ response = input ("Are the above changes okay? [y/N]: " )
74
89
if response .upper () in ['Y' , 'YES' ]:
75
- rename_mangled (args .roots , False ) # really rename
90
+ rename_mangled (args .roots , False , args . recursive ) # really rename
76
91
77
92
78
93
if __name__ == '__main__' :
0 commit comments