-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathnospaces.py
105 lines (92 loc) · 3.03 KB
/
nospaces.py
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
#!/usr/bin/env python
# file: nospaces.py
# vim:fileencoding=utf-8:ft=python
#
# Copyright © 2024 R.F. Smith <[email protected]>
# SPDX-License-Identifier: MIT
# Created: 2024-01-20T10:59:10+0100
# Last modified: 2024-01-27T00:05:00+0100
"""Replaces spaces in filenames with underscores.
It processes the file names given on the command line.
"""
import argparse
import logging
import os
import re
import sys
__version__ = "2024.01.26"
def main():
"""
Entry point for .py.
"""
options = setup()
for path in options.files:
if os.path.isfile(path):
if path.startswith("."):
logging.info(f"skipping hidden file “{path}”")
continue
if not options.dryrun:
rename(path, options.replace)
else:
newpath = new_path(path, options.replace)
if newpath:
print(f"“{path}” would be renamed to “{newpath}”")
def setup():
"""Program initialization"""
# Process command-line arguments
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("-v", "--version", action="version", version=__version__)
parser.add_argument(
"--log",
default="warning",
choices=["debug", "info", "warning", "error"],
help="logging level (defaults to 'warning')",
)
parser.add_argument(
"-d", "--dryrun", action="store_true",
help="do not rename, but show what would be renamed"
)
parser.add_argument(
"-r", "--replace", type=ord, default="_",
help="code point to use for replacing whitespace (defaults to '_')"
)
parser.add_argument(
"files", metavar="file", nargs="*",
help="one or more files or directories to process"
)
args = parser.parse_args(sys.argv[1:])
# Configure logging
logging.basicConfig(
level=getattr(logging, args.log.upper(), None),
format="%(levelname)s: %(message)s",
)
logging.debug(f"replacement: ‘{args.replace}’")
args.replace = chr(args.replace)
logging.debug(f"args = {args}")
if args.replace.isspace():
logging.warning("replacing whitespace with whitespace doesn't make sense; exiting")
sys.exit(0)
return args
def new_path(path, rep="_"):
"""Return new name for path."""
head, tail = os.path.split(path)
newpath = os.path.join(head, re.sub("[-_]?\s+[-_]?|[-_]+", rep, tail))
if newpath == path:
return None
return newpath
def rename(path, rep="_"):
"""Change the name of the file at the end of path, replacing whitespace
with the contents of rep."""
head, tail = os.path.split(path)
newpath = new_path(path, rep)
if not newpath:
logging.info(f"{path} unchanged")
return
try:
os.replace(path, newpath)
except OSError as e:
logging.error(f"renaming “{path}” to “{newpath}” failed: {e}")
else:
logging.info(f"“{path}” has been renamed to “{newpath}”")
if __name__ == "__main__":
main()