Clean Up File Names in Bulk (Free Python Script)
Free Python script that renames every file in a folder to clean, lowercase, web-safe names: no spaces, accents or symbols.
Download clean-filenames-snake-case.pyPython 3 · 93 lines · 3 KB · free
File names with spaces, capitals, accents and symbols cause trouble: broken links on websites, upload errors on marketplaces and messy URLs. This script renames every file in a folder to a clean, lowercase name in one go.
What it does
- Turns
My Photo (Final) #2.JPGintomy_photo_final_2.jpg - Turns
Café Menü.PNGintocafe_menu.png - Replaces spaces and symbols with a single underscore
- Converts accented letters to plain ones and makes everything lowercase, including the extension
- If two files would end up with the same name, adds
_1,_2and so on, so nothing is overwritten - Leaves hidden system files and subfolders alone
It works on the files directly inside the folder you give it, not in subfolders.
How to use it
- Run the script (see below).
- When it asks
Enter folder path:, paste the path of your folder, or drag the folder into the terminal window, and press Enter. - The script prints every change, for example
Renamed: My Photo.JPG -> my_photo.jpg.
Renaming cannot be undone with Ctrl+Z. Run the script on a copy of the folder the first time, until you trust the result.
How to run a Python script
- Install Python 3 from python.org if you do not have it. It is free. On Windows, tick Add Python to PATH in the installer.
- Download the script with the button on this page and save it somewhere easy, such as your Desktop.
- Open a terminal. On Windows, press the Windows key, type
cmdand press Enter. On Mac, open Terminal from Applications > Utilities. - Type
pythonfollowed by a space (on Mac,python3and a space), drag the script file into the terminal window and press Enter.
Why clean file names matter
- Websites: a space in a file name becomes
%20in the address. Lowercase names with no symbols work on every server. - Search engines: image file names are read as a hint about the picture.
red_running_shoes.jpgsays more thanIMG_4032.JPG. - Marketplaces and stock sites: many upload forms reject names with special characters.
- Sharing between Windows, Mac and Linux: characters such as
:?and*are not allowed on Windows.
Questions
Can I use hyphens instead of underscores?
Yes. Run this script first, then run the find and replace script on the same folder to swap _ for -.
Does it rename files in subfolders?
No, only the files directly in the folder you enter. Run it once per folder.
What happens to names in other alphabets?
Letters with accents are converted to plain letters. Characters with no plain equivalent, such as Arabic or Chinese, are removed. A file whose whole name is removed is called file.
The code
This is the complete script. Nothing else is downloaded or installed.
"""Clean file names (snake_case)
Renames every file in one folder to a clean, lowercase, web-safe name:
"My Photo (Final) #2.JPG" becomes "my_photo_final_2.jpg".
Free script from LinearAndLoom Icons: https://linearandloomicons.netlify.app/scripts/
Provided as is. Renaming and zipping cannot be undone, so try it on a copy of your folder first.
"""
import re
import unicodedata
from pathlib import Path
def to_snake_case_filename(filename: str, max_length: int = 180) -> str:
"""
Convert filename to clean SEO-friendly snake_case.
Preserves extension and removes invalid characters.
"""
path = Path(filename)
stem = path.stem
suffix = path.suffix.lower()
# Normalize unicode → ASCII
stem = unicodedata.normalize("NFKD", stem)
stem = stem.encode("ascii", "ignore").decode("ascii")
# Lowercase for snake_case
stem = stem.lower()
# Remove invalid filename chars (Windows + cross-platform safe)
stem = re.sub(r'[<>:"/\\|?*\x00-\x1F]', "", stem)
# Replace any non-alphanumeric sequence with underscore
stem = re.sub(r"[^a-z0-9]+", "_", stem)
# Remove repeated underscores
stem = re.sub(r"_+", "_", stem)
# Strip leading/trailing underscores
stem = stem.strip("_")
# Prevent empty names
if not stem:
stem = "file"
# Trim total length safely
max_stem_len = max_length - len(suffix)
stem = stem[:max_stem_len].rstrip("_")
return stem + suffix
def normalize_folder_filenames(folder_path: str):
folder = Path(folder_path)
if not folder.exists() or not folder.is_dir():
print("Invalid folder path.")
return
used_names = set()
this_script = Path(__file__).resolve()
# List the files first, so files renamed along the way are not picked up twice
for file in sorted(f for f in folder.iterdir() if f.is_file()):
# Leave hidden system files (.DS_Store, .gitignore) and this script alone
if file.name.startswith(".") or file.resolve() == this_script:
continue
new_name = to_snake_case_filename(file.name)
new_path = folder / new_name
# Handle duplicates
base_stem = Path(new_name).stem
suffix = Path(new_name).suffix
counter = 1
# samefile() keeps "Photo.JPG" -> "photo.jpg" working on Windows and macOS,
# where both names point to the same file
while new_name in used_names or (new_path.exists() and not new_path.samefile(file)):
new_name = f"{base_stem}_{counter}{suffix}"
new_path = folder / new_name
counter += 1
used_names.add(new_name)
if file.name != new_name:
file.rename(new_path)
print(f"Renamed: {file.name} -> {new_name}")
if __name__ == "__main__":
folder_path = input("Enter folder path: ").strip().strip('"').strip("'")
normalize_folder_filenames(folder_path)Download clean-filenames-snake-case.pyPython 3 · 93 lines · 3 KB · free
These scripts are free. If one saved you time, you can say thanks by buying a pack from the LinearAndLoom Etsy shop.


