Often I need to work with files that have really long and obscure names. rename
is a Python script I wrote that renames a given file using a sane format. By default, it makes the following changes:
- Remove all whitespace and punctuation marks
- Remove English stopwords
- Lowercase all characters and
- Hyphenate everything
Here is the full script as of 2024-11-29, you can find the latest version of the script in my dotfiles repository.
rename
#!/usr/bin/env python3
import argparse
import os
import re
with open(
"HOME"), ".local/share/rename", "stopwords-en.txt")
os.path.join(os.getenv(as f:
) = f.readlines()
STOPWORDS = [word.strip("\n") for word in STOPWORDS]
STOPWORDS
def rename(src: str) -> str:
= src
dst = dst.lower()
dst = re.sub(r"\s+", "-", dst) # replace 1 or more whitespace with hyphen
dst = re.sub(
dst r"[^a-zA-Z0-9]+", "-", dst
# replace 1 or more punctuations with hyphen
) = re.sub("([A-Z][a-z]+)", r"-\1", re.sub("([A-Z]+)", r"-\1", dst))
dst = dst.split("-")
dst = [word for word in dst if word] # remove empty words
dst = [word for word in dst if word not in STOPWORDS]
dst return "-".join(dst)
if __name__ == "__main__":
= argparse.ArgumentParser(description="Rename files the way I like it.")
parser "source", type=str, help="File or directory to rename")
parser.add_argument(
parser.add_argument("-f",
"--force",
="store_true",
action=False,
defaulthelp="Don't ask for confirmation",
)
= parser.parse_args()
args
= os.path.split(args.source)
head, tail = os.path.splitext(tail)
src, ext
= rename(src)
dst = os.path.join(head, dst)
dst = f"{dst}{ext}"
dst
if not dst:
print("rename: no more words left!")
1)
exit(
if not args.force:
= input(f"rename: {args.source} --> {dst}? [y, n]: ")
response match response:
case "n":
print("rename: aborted by user.")
0)
exit(case _:
print("rename: incorrect response, please type one of [y, n]")
1)
exit(
print(f"rename: {args.source} --> {dst}")
=args.source, dst=dst) os.rename(src
The stopwords are read from a text file so adding new stopwords (or words you never want to see in your filenames) easy. I store this file in my dotfiles repo to ensure that the rename
script works on any machine where I clone my system configuration files.
By default, the script will ask for confirmation before renaming a file. The --force
flag can be passed to bypass this. This makes it convenient to rename files in bulk using standard unix tools such as find
and xargs
. For instance, below how I show how you can rename all Docx files in a directory automatically.
find * -name '*.docx' -print0 |
xargs -0 -n1 rename --force