Set team file-naming rules and check filenames with Python
Define a simple team filename convention, test it on a synthetic folder, and write a review report without renaming or deleting anything. The checker separates structural errors, invalid dates, and unsupported extensions.
Content checked 2026.09.20Hand-checked example
Show contents
Who this is forThis guide is for teams that want predictable filenames and a simple automated check before files are shared or archived.
What you need
Python 3.12 and a terminal command that starts that version.
A working folder where the scripts can create folders beneath outputs.
Agreement on the project codes, document labels, version format, and allowed extensions your team will use.
Only the Python standard library is required: csv, datetime, pathlib, and re.
01Write the naming convention before writing the checker
This example uses the format YYYYMMDD_project_document_vNN.ext. The date is eight digits and must be a real calendar date. project and document use lowercase letters or digits, optionally separated by hyphens. The version is v followed by exactly two digits. The allowed extensions are pdf, docx, xlsx, csv, and txt.
Use underscores only between the four main filename parts.
Use v01, v02, and so on for versions instead of final, latest, new, or revised.
Keep the original file extension and restrict it to an agreed list.
02Create a synthetic folder with valid and invalid names
The following filenames are synthetic and were written specifically for this article. Save the setup script as create_file_naming_demo.py. It creates eight empty files; four follow the rule and four deliberately violate it.
python
from pathlib import Path
SOURCE = Path("outputs") / "file_naming_demo"
FILENAMES = [
"20260920_alpha_test-plan_v01.pdf",
"20260920_alpha_results_v02.csv",
"20260921_beta_meeting-notes_v03.txt",
"20261001_beta_budget_v01.xlsx",
"2026-09-20_alpha_notes_v01.txt",
"20260920_Alpha_notes_v01.txt",
"20260920_alpha_notes_final.txt",
"20260230_beta_results_v01.csv",
]
SOURCE.parent.mkdir(parents=True, exist_ok=True)
SOURCE.mkdir() # Stop if the synthetic source already exists.
for filename in FILENAMES:
target = SOURCE / filename
with target.open("xb"):
pass
The first four names are expected to pass. The fifth uses a hyphenated date instead of YYYYMMDD. The sixth contains an uppercase project token. The seventh uses final instead of vNN. The eighth has the correct shape but contains the impossible date 2026-02-30.
03Classify the eight names by hand
Filename
Expected status
Reason
20260920_alpha_test-plan_v01.pdf
PASS
Matches structure and date is valid
20260920_alpha_results_v02.csv
PASS
Matches structure and date is valid
20260921_beta_meeting-notes_v03.txt
PASS
Matches structure and date is valid
20261001_beta_budget_v01.xlsx
PASS
Matches structure and date is valid
2026-09-20_alpha_notes_v01.txt
FAIL
STRUCTURE_ERROR
20260920_Alpha_notes_v01.txt
FAIL
STRUCTURE_ERROR
20260920_alpha_notes_final.txt
FAIL
STRUCTURE_ERROR
20260230_beta_results_v01.csv
FAIL
INVALID_DATE
The expected totals are therefore 8 files checked, 4 passes, and 4 failures. Three failures are structural and one has a structurally valid filename but an invalid calendar date.
04Check filenames without renaming them
Save the following script as check_file_names.py. It reads filenames only and writes a CSV report into a separate output folder. It does not rename, move, edit, or delete any source file.
python
import csv
import re
from datetime import datetime
from pathlib import Path
SOURCE = Path("outputs") / "file_naming_demo"
OUTPUT_DIR = Path("outputs") / "file_naming_result"
REPORT = OUTPUT_DIR / "file_naming_report.csv"
ALLOWED_EXTENSIONS = {"pdf", "docx", "xlsx", "csv", "txt"}
NAME_PATTERN = re.compile(
r"^(?P<date>[0-9]{8})_"
r"(?P<project>[a-z0-9]+(?:-[a-z0-9]+)*)_"
r"(?P<document>[a-z0-9]+(?:-[a-z0-9]+)*)_"
r"(?P<version>v[0-9]{2})\."
r"(?P<extension>[a-z0-9]+)$"
)
def check_filename(filename: str) -> tuple[str, str]:
match = NAME_PATTERN.fullmatch(filename)
if match is None:
return "FAIL", "STRUCTURE_ERROR"
extension = match.group("extension")
if extension not in ALLOWED_EXTENSIONS:
return "FAIL", "UNSUPPORTED_EXTENSION"
try:
datetime.strptime(match.group("date"), "%Y%m%d")
except ValueError:
return "FAIL", "INVALID_DATE"
return "PASS", ""
def main() -> None:
if not SOURCE.is_dir():
raise FileNotFoundError(f"Source folder not found: {SOURCE}")
if OUTPUT_DIR.exists():
raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")
files = sorted(path for path in SOURCE.iterdir() if path.is_file())
results = []
for path in files:
status, issue = check_filename(path.name)
results.append({
"filename": path.name,
"status": status,
"issue": issue,
})
OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
OUTPUT_DIR.mkdir()
with REPORT.open("x", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(
stream,
fieldnames=["filename", "status", "issue"],
)
writer.writeheader()
writer.writerows(results)
passed = sum(row["status"] == "PASS" for row in results)
failed = len(results) - passed
print(f"Files checked: {len(results)}.")
print(f"Passed: {passed}; failed: {failed}.")
print(f"Report: {REPORT.as_posix()}")
if __name__ == "__main__":
main()
text
python check_file_names.py
05Compare the expected report
The report should contain one row for every source file. Because filenames are sorted alphabetically before checking, the output order follows the sorted names rather than the setup-script list.
Expected count
Value
Files checked
8
PASS
4
FAIL
4
STRUCTURE_ERROR
3
INVALID_DATE
1
The expected console output below was derived by hand from the synthetic filenames and checker. It is not a captured execution log.
Confirm that all four intended valid names receive PASS.
Confirm that 20260230_beta_results_v01.csv is rejected even though its text shape matches the regex.
Decide who is allowed to rename shared files before correcting anything.
Check links, scripts, CAD references, document references, or shared-drive shortcuts that may depend on existing filenames.
Run the checker again without changing OUTPUT_DIR. It should stop with FileExistsError instead of replacing the previous report.
Problem
What to check
Many STRUCTURE_ERROR results
Confirm that the written team rule matches the naming practice people actually use.
Uppercase or spaces appear frequently
Decide whether to prohibit them consistently or revise the rule instead of fixing files ad hoc.
A valid-looking date fails
Check whether the YYYYMMDD text represents a real calendar date.
Users keep writing final or latest
Use explicit version numbers and define when a file becomes approved or released separately.
Renaming breaks references
Do not automate renaming until dependent systems and links have been assessed.
07Keep naming rules useful rather than overly complicated
A filename convention cannot replace proper version control, document management, or metadata. A file called v03 does not prove that it is newer in content than v02, approved by the correct person, or linked to the correct project.
The example checks files directly inside one folder only. It does not recursively scan subfolders, enforce uniqueness across multiple shared drives, check file contents, or verify that the project token corresponds to a real project.
When a team changes its convention, record the effective date and decide whether old files are grandfathered or renamed. A practical rule should be stable enough for people to remember and strict enough for automated checks to produce useful results.
Execution and verification record
2026-09-20 · hand-checked example · target: Python 3.12 · standard library: csv, datetime, pathlib, re · no execution
Manually classified 8 synthetic filenames as 4 valid and 4 invalid.
Identified three structural failures: the hyphenated date, uppercase project token, and final version label.
Confirmed by calendar reasoning that 2026-02-30 is invalid even though 20260230 matches the eight-digit date shape.
Manually derived expected totals of 4 PASS, 4 FAIL, 3 STRUCTURE_ERROR, and 1 INVALID_DATE.
Inspected the script for full filename matching, allowed-extension checking, calendar-date validation, output collision protection, and absence of rename or delete operations.
Derived the expected console output by hand.
Verification limits
The code was not executed by the author of this response; no files or reports were created.
Recursive folders, shared-drive links, case-insensitive filesystem behavior, cross-project uniqueness, and dependent application references were not tested.
The naming convention is an example team policy and should be changed to fit the actual workflow.
The official documentation URLs were provided from known documentation locations but were not checked live.
Turn raw release notes into a changelog entry that separates changes from required user actions and verification steps. A synthetic software update shows how to make a release note useful to someone who did not make the change.
Turn project handover notes into a structured checklist that records what must be transferred, who owns it, where it is stored, and what remains unresolved. A small synthetic example shows how to detect missing owners, locations, and open-issue details before handover.
Instead of stopping at another summary of the meeting, separate agreed work from open items. Turn synthetic meeting notes into a list with owners, due dates, deliverables, and evidence of completion, and write an AI request that assists with the same task.
Manage each article as one row and separate drafting, review, approval, and publishing. Covers importing a local CSV, dropdowns, filter views, sharing permissions, and version history, and sets up a flow for manually updating site files after approval.