Create your own
Lesson illustration

Downloads Organizer Behavior Specification

Welcome to the first build day of your Python scripting course. Over the next ten study days, you will develop a practical Downloads-folder organizer while learning habits that transfer to many other automation scripts: define behavior precisely, separate work into functions, preview changes, and handle unexpected cases safely.

Today begins before code. A script that moves files can be useful, but it can also be destructive if its behavior is vague. Your goal is to write a compact specification: a decision document that says exactly what the organizer will and will not do. That specification will become the blueprint for every function we build next.


Start with the script’s purpose and scope

A behavior specification is not a technical implementation plan. It should describe observable results, not prematurely decide whether you will use a particular Python method or library.

For example:

  • Too technical: “Use Path.iterdir() and shutil.move().”
  • Behavioral: “Inspect only files directly inside the selected folder and move each eligible file into its category folder.”

The first tells us how; the second tells us what must be true when the script works. We will decide the how in later lessons.

The purpose of this project is deliberately modest:

Organize the files directly inside a chosen folder, normally Downloads, into clearly named category folders based on file extension, without overwriting or silently losing files.

That framing also tells us what this first version is not:

  • It is not a background program that continually watches Downloads.
  • It does not inspect file contents to determine their type.
  • It does not organize files inside subfolders.
  • It does not delete duplicate files.
  • It does not need a graphical interface or a database.

Keeping this scope small is good project planning, not a limitation. The planning approach in How I Plan My Coding Projects emphasizes defining user-facing behavior first, then keeping the initial version to the minimum functionality that is genuinely useful.

How I Plan My Coding Projects - 9 Steps

Watch “How I Plan My Coding Projects - 9 Steps” by Tech With Tim for a concise model of turning an idea into user-centered requirements and protecting a project from unnecessary scope.

Watch user stories to see how requirements can describe what a user should be able to do without prematurely specifying technical details. Then watch the MVP, focusing on the question: “Is this necessary for the first useful version?”

For our script, the central user story is:

As the owner of a cluttered Downloads folder, I want to preview and then organize eligible files into category folders, so that I can find them more easily without risking existing files or folders.

Notice the important constraints embedded in that sentence: eligible, preview, and without risking. A specification must define each one.


Turn ambiguous words into decisions

Words such as “file,” “organize,” and “safe” seem obvious until a script encounters a case you did not consider.

Suppose Downloads contains this:

Downloads/
    invoice.PDF
    family-photo.jpg
    setup.EXE
    notes
    browser-download.crdownload
    Images/
        old-photo.png

Questions immediately appear:

  • Does “file” include the Images directory?
  • Should old-photo.png be moved too?
  • Is invoice.PDF a document even though its extension is uppercase?
  • What happens to notes, which has no extension?
  • Should an unfinished browser download be moved?
  • What if Documents/invoice.PDF already exists?

A reliable specification gives an answer before you write the code.

The intended organization is extension-based: the final part of a filename helps select a folder. The illustration below shows the general idea. Our organizer will use a broader, practical set of categories and will preserve the original filenames.

A folder organization concept in which files are placed into category folders based on their extensions; our script will apply the same principle to files directly inside Downloads.

A key distinction:

  • A category is a destination label such as Documents or Images.
  • An extension is a filename ending such as .pdf or .jpg.
  • A mapping is the rule connecting extensions to categories.

For the first version, use the following category rules. They are intentionally understandable and easy to change later.

Category folderExtensions, compared without regard to uppercase or lowercase
Documents.pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .txt, .csv
Images.jpg, .jpeg, .png, .gif, .webp, .bmp
Audio.mp3, .wav, .m4a
Videos.mp4, .mov, .mkv
Archives.zip, .7z, .rar, .tar, .gz
Installers.exe, .msi
Code.py, .js, .html, .css, .json, .toml
OtherAny unlisted extension, or no extension

This table gives the script deterministic behavior:

  • REPORT.PDF belongs in Documents because .PDF is normalized to .pdf before lookup.
  • archive.tar.gz belongs in Archives; for this first version, the final extension .gz is enough to make that decision.
  • notes has no extension, so it belongs in Other.
  • diagram.vsdx is not in the mapping, so it also belongs in Other.

The fallback category matters. Without it, every unfamiliar file type becomes an unplanned special case. With it, the script remains useful while never pretending it understands more than it does.


Define eligibility and exclusions

The organizer should inspect only regular files directly inside the source folder. “Directly inside” means its immediate contents only, not a recursive search through every folder below it.

This is both a safety decision and a usability decision. A nested folder may have its own structure that should remain untouched. It also means that once the organizer creates folders like Documents and Images, later runs will leave those folders and everything inside them alone.

Write the eligibility rule in this form:

A file is eligible when it is a regular file whose direct parent is the selected source folder, and it is not excluded by a safety rule.

For this project, the exclusions are:

  1. Directories are excluded. The script must not move category folders, existing folders, or any folder contents.
  2. Nested files are excluded. The script must not search inside folders.
  3. Incomplete downloads are excluded. Files ending in .crdownload, .part, or .tmp are skipped. A browser or another application may still be writing them.
  4. The organizer script itself is excluded if it is placed in the source folder. In practice, keep your Python project folder outside Downloads, but the intended behavior should still avoid moving the running script.
  5. Nothing is excluded merely because it is unknown or extensionless. Those files belong in Other.

The distinction in item 5 is important: “unknown” is a classification result, whereas “excluded” means the script deliberately leaves an item alone.


Specify destinations using predictable paths

For every eligible file, the destination consists of:

  1. the chosen source folder;
  2. the category folder selected by the mapping;
  3. the original filename.

For example, if the source folder is:

C:\Users\Sam\Downloads

then these planned destinations are:

Source fileCategoryIntended destination
invoice.PDFDocumentsC:\Users\Sam\Downloads\Documents\invoice.PDF
photo.jpgImagesC:\Users\Sam\Downloads\Images\photo.jpg
notesOtherC:\Users\Sam\Downloads\Other\notes

The category folders should be created only when an actual move needs them. During a preview, the script should merely report that it would create or use a folder; preview mode must not change the file system.

Because this project runs on Windows, paths and names have a few consequences for safe behavior. Windows normally treats names that differ only in capitalization as the same name. Thus Report.pdf and report.pdf must be treated as a possible collision, not as safely separate destination files.

Naming Files, Paths, and Namespaces - Win32 apps

Read the “Naming Conventions” guidance from Microsoft Learn to understand the Windows assumptions behind safe file and folder handling.

In the “Naming Conventions” section, read the Windows naming guidance. Focus on three ideas: a period separates a name from its extension, backslashes separate path components, and Windows should not be assumed to distinguish names only by capitalization. Also note the reserved characters and names; our fixed category names avoid creating folders from unsafe text.

Our script will not invent category names from downloaded filenames. It creates only known folder names such as Documents, Images, and Other, and it normally preserves the original filename.


Make “safe” observable

“Be careful” is not a requirement a program can follow. A safe specification instead states guarantees that someone could verify after a run.

For this organizer, safety means:

SituationRequired behavior
The source folder does not exist or cannot be accessedStop before moving anything and report the problem.
The script is in preview modeDisplay each planned move; create no folders and move no files.
A category folder does not exist during an actual runCreate that category folder before moving the relevant file.
A same-named destination file already existsNever overwrite it. Select a distinct unused destination name, such as invoice (1).pdf.
A file cannot be movedLeave that source file in place and report the failure.
The script sees an excluded itemLeave it untouched and report it as skipped.
A file is moved successfullyThe file should no longer be directly in the source folder and should exist at its reported destination.

Two choices here are particularly valuable:

Preview first. Before allowing real moves, you should be able to inspect a list such as:

PLAN: invoice.PDF  |  Documents  |  C:\Users\Sam\Downloads\Documents\invoice.PDF
PLAN: notes        |  Other      |  C:\Users\Sam\Downloads\Other\notes
SKIP: browser-download.crdownload  |  incomplete download
SKIP: Images  |  directory

Never overwrite. A name collision is not proof that two files are identical. For the initial script, the conservative choice is to retain both files under distinct names. We will implement this later; today, your specification establishes the rule we must satisfy.


Your version 1 behavior specification

Use the following as the working specification for the project. Save it in a notes file alongside your future Python script. Its value is that it is specific enough to guide coding and testing, yet short enough to revise.

Downloads Organizer: Version 1 Specification

Purpose
Organize files directly inside a user-selected source folder, normally Downloads, into category folders based on their filename extensions.

Input
A source folder chosen when the script is launched. The folder must exist and be accessible.

Eligible items
Process regular files directly inside the source folder only.

Excluded items

  • All directories and their contents
  • Files inside subdirectories
  • Files ending in .crdownload, .part, or .tmp, ignoring case
  • The organizer script itself if it is directly inside the source folder

Classification rules

  • Determine the file’s final extension.
  • Compare extensions after converting them to lowercase.
  • Use the category mapping defined in this lesson.
  • Put files with an unrecognized extension or no extension in Other.

Destination rules

  • Put each eligible file in a folder named for its category, directly inside the source folder.
  • Preserve the original filename whenever possible.
  • Create a missing category folder only during an actual move, never during a preview.

Safety rules

  • Begin with preview behavior: list planned actions without modifying files or folders.
  • Never overwrite an existing destination file, including one whose name differs only by capitalization.
  • When a destination name is already taken, use a unique non-overwriting name.
  • Do not delete files as a way to resolve duplicates.
  • Report each item as planned, moved, skipped, or failed.
  • If a particular file causes an error, leave it in place and continue with other files when possible.

Out of scope for version 1

  • Recursively organizing subfolders
  • Identifying file types from file contents
  • Deleting duplicates
  • Automatically running in the background
  • Sorting photos by date or creating elaborate folder structures

This specification is a contract for the script. When we later write code, avoid adding behavior casually. If you want a new behavior, add it deliberately to the specification first.


Wrap-up

You now have a practical definition of what the Downloads organizer must do:

  • It processes only direct, eligible files in a selected folder.
  • It normalizes extensions, uses a clear category mapping, and sends unknown or extensionless files to Other.
  • It leaves folders, nested contents, incomplete downloads, and its own script alone.
  • It uses predictable category destinations.
  • It protects data through previewing, non-overwriting destinations, and clear reporting.

Next, we will begin implementation with the smallest useful building block: a pathlib function that returns only the files directly inside a specified folder. That function will enforce the boundary your specification established today.

Can't find a good explanation? Sign up and we'll make it for you

Sign up