Tony CantaveHow I Automate Repetitive File Tasks With a Small Python Script
By Tony Cantave ·
Every job I have had came with some version of the same chore: a folder fills up with files, and someone has to sort them, rename them, and move them where they belong. In logistics it was route sheets and delivery manifests. In manufacturing it was production exports from the ERP system. Today it is screenshots, rubric notes, and media files from AI evaluation work. The chore never goes away, but it does not have to be done by hand.
Here is the small Python pattern I use whenever a manual file task starts eating more than a few minutes a day.
Start by writing the task down in plain words
Before I write any code, I describe the job in one or two sentences. For example: "Every PDF in the Downloads folder that starts with invoice should move into a folder named by year and month, and the file name should start with the date." If I cannot describe it that simply, the script will be messy too. Writing it down also shows me the rules I apply without thinking, like which files to ignore.
The basic script
Python's standard library already has everything this needs. There is nothing to install.
from pathlib import Path
from datetime import datetime
import shutil
SOURCE = Path.home() / "Downloads"
DEST_ROOT = Path.home() / "Documents" / "Invoices"
DRY_RUN = True # change to False once the output looks right
def target_for(file):
modified = datetime.fromtimestamp(file.stat().st_mtime)
folder = DEST_ROOT / modified.strftime("%Y_%m")
new_name = modified.strftime("%Y_%m_%d") + "_" + file.name
return folder / new_name
for file in sorted(SOURCE.glob("invoice*.pdf")):
target = target_for(file)
if target.exists():
print(f"SKIP {file.name} (already exists at {target})")
continue
print(f"MOVE {file.name} to {target}")
if not DRY_RUN:
target.parent.mkdir(parents=True, exist_ok=True)
shutil.move(str(file), str(target))Why the dry run matters
The DRY_RUN flag is the most important line in the script. The first time I run anything that moves or renames files, I want it to print what it would do and touch nothing. I read the output, and only when every line looks right do I flip the flag. This habit came straight from production work: you never run a new process on the real line until you have watched it on a test batch.
Never overwrite silently
Notice the check for an existing file. If two files would end up with the same name, the script skips and tells me instead of replacing one with the other. Losing a file quietly is the worst outcome for an automation, because you do not find out until you need that file weeks later. A skipped file just shows up in the output, and I deal with it.
Keep a log
Printing to the screen is fine while I am testing. Once a script runs on its own, I want a record. Python's logging module handles that in a few lines:
import logging
logging.basicConfig(
filename=Path.home() / "file_mover.log",
level=logging.INFO,
format="%(asctime)s %(message)s",
)Then I swap the print calls for logging.info. When something looks off a week later, I can open the log and see exactly which file went where, and when.
Run it on a schedule
On Linux or a Mac, cron runs the script automatically. On Windows, Task Scheduler does the same job. I usually start with once a day, early in the morning. A crontab line like this runs it at 6 AM every day:
0 6 * * * /usr/bin/python3 /home/tony/scripts/file_mover.pySmall rules I follow
- One script, one job. If I want to sort invoices and also clean up screenshots, those are two scripts. They are easier to test and easier to turn off.
- Use pathlib instead of string paths. It handles slashes across operating systems and makes the code easier to read.
- Match narrowly. A pattern like invoice*.pdf is safer than *.pdf. The wider the pattern, the more likely the script grabs something it should not.
- Test on a copy first. I make a test folder with a handful of sample files and point SOURCE at it before going near the real folder.
Where this pays off
The time saved on one task is small, maybe five or ten minutes a day. The real value is consistency. Files land in the same place with the same naming every time, which makes everything downstream easier: searching, backing up, and handing work to someone else. That is the same lesson I learned running routes and production schedules. A process that runs the same way every day beats a heroic effort once in a while.
If you have a folder you clean up by hand every week, try writing the rule down in one sentence and turning it into a dry run script. You will probably be surprised how little code it takes.