Skip to content

Instantly share code, notes, and snippets.

@jasonbot
Last active October 8, 2025 15:28
Show Gist options
  • Save jasonbot/a5e5ec420bc87ec31e9ed20ac865f981 to your computer and use it in GitHub Desktop.
Save jasonbot/a5e5ec420bc87ec31e9ed20ac865f981 to your computer and use it in GitHub Desktop.
My work-in-progress "illegal character killer"
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