Last active
October 8, 2025 15:28
-
-
Save jasonbot/a5e5ec420bc87ec31e9ed20ac865f981 to your computer and use it in GitHub Desktop.
My work-in-progress "illegal character killer"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import collections | |
import itertools | |
import os | |
import pathlib | |
import sys | |
REPLACE_TUPLES = (("/.", "/"),) | |
REPLACE_CHARS = ':*?"![]' | |
VERY_REPLACE = {'$': 'S'} | |
def walk(path: pathlib.Path): | |
if not path.exists(): | |
print(path, "went away") | |
return | |
for item in list(path.iterdir()): | |
if item.is_dir(): | |
yield item | |
yield from walk(item) | |
elif item.is_file(): | |
yield item | |
def need_rename(filename: pathlib.Path): | |
if filename.is_dir(): | |
c = collections.Counter(f.name.lower() for f in filename.parent.iterdir()) | |
if c[filename.name.lower()] > 1: | |
newfn = next( | |
f.name | |
for f in filename.parent.iterdir() | |
if f.name.lower() == filename.name.lower() | |
) | |
if filename.name != newfn: | |
return filename.parent / newfn | |
elif ( | |
any(c in str(filename) for c in REPLACE_CHARS) | |
or any(c in str(filename) for c, _ in REPLACE_TUPLES) | |
or filename.name.startswith(".") | |
): | |
if filename.name.startswith("."): | |
filename = filename.parent / ("_" + filename.name.lstrip(".")) | |
for c in REPLACE_CHARS: | |
filename = str(filename).replace(c, "_") | |
for c, v in VERY_REPLACE.items(): | |
filename = str(filename).replace(c, v) | |
for old, new in REPLACE_TUPLES: | |
filename = str(filename).replace(old, new) | |
filename = str(filename).replace("/.", "/") | |
np = pathlib.Path(filename) | |
return np | |
p = pathlib.Path(".") | |
doit = "--do-it" in sys.argv | |
for file in walk(p): | |
if rename_to := need_rename(file): | |
print(file, "->", rename_to) | |
if file.is_file(): | |
if doit: | |
try: | |
os.makedirs(rename_to.parent) | |
except: | |
pass | |
os.rename(file, rename_to) | |
elif file.is_dir(): | |
for item_to_move in file.iterdir(): | |
new_path = rename_to / item_to_move.name | |
print(" ", item_to_move, "->", new_path) | |
if doit: | |
pp = str(new_path) | |
for ii in range(1, 10): | |
try: | |
os.rename(item_to_move, pp) | |
break | |
except OSError as e: | |
pp = f"{str(new_path)}_{ii+1}" | |
print(f" {e}: trying") | |
if doit: | |
os.rmdir(file) | |
if not doit: | |
print("If you like this course of events, use --do-it and rerun") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment