Project D - Sorteer foto's op datum
01 - Projectoverzicht
- In dit project maak je een Python-script dat foto's automatisch sorteert in mappen per jaar en maand.
- Het script lost het probleem op van een downloadmap of telefoonbackup waarin honderden foto's door elkaar staan.
- Je gebruikt een testmap met kopieën van JPG- en PNG-bestanden.
- Het script bepaalt de datum via de bestandsdatum en plaatst foto's bijvoorbeeld in mappen zoals
2026/05. - Het resultaat is een overzichtelijke fotomap waarin afbeeldingen chronologisch zijn ingedeeld.
- Je gebruikt AI om code te laten genereren die eerst toont welke kopieën gemaakt zouden worden.
- Je voert de code uit in VS Code en controleert daarna de nieuwe mapstructuur in Finder of Verkenner.
- Als foto's verkeerd worden ingedeeld, verbeter je de prompt met regels voor datumgebruik, bestandstypen en veilige testmodus.
02 - Projectmap en Python-omgeving
Voorkennis: doorloop de voorgaande projecten. Het doel en gebruik van .venv zijn uitgelegd in project A, blok 02. Voor ieder nieuw project maak je een eigen omgeving; hieronder herhaal je die bekende stappen.
- Maak een eigen projectmap
project_den open die map in VS Code. Maak daarin straksfotos_sorteren.py. - Deze oefeningen voer je lokaal uit in de terminal van VS Code, omdat ze bestanden op je computer lezen of schrijven. Gebruik hiervoor de Python-installatie uit de basiscursus.
- Controleer je Python-versie. Werkt
pythonop macOS of Linux niet, gebruik danpython3voor het aanmaken van de omgeving.
python --version
python -m venv .venv
Activeer de omgeving. In Windows PowerShell:
.venv\Scripts\Activate.ps1
In de Windows-opdrachtprompt (cmd):
.venv\Scripts\activate.bat
Op macOS of Linux:
source .venv/bin/activate
Kies in VS Code via Python: Select Interpreter de interpreter uit .venv. Gebruik vanaf nu de geactiveerde terminal. Je verlaat de omgeving later met deactivate.
Dit project gebruikt alleen de standaardbibliotheek van Python. Extra pakketten installeren is niet nodig.
03 - Testgegevens voorbereiden
Maak invoer met enkele kopieën van echte JPG- en PNG-foto’s. De map gesorteerd wordt automatisch naast invoer aangemaakt. In deze eerste versie kopiëren we de foto’s; pas later kun je een verplaatsfunctie onderzoeken.
We gebruiken de laatste wijzigingsdatum van het bestand, in lokale tijd. Dat is niet altijd de datum waarop de foto is genomen. Controleer deze datum eerst in Finder of Verkenner.
04 - Begrippen en hulpmiddelen vóór de opdracht
- datetime zet een tijdstempel om naar een datum.
fromtimestampgebruikt de lokale tijdzone.%Yis het jaar en%mde maand. - shutil is de standaardmodule voor bestandsbewerkingen;
copy2(bron, doel)kopieert een bestand. We kopiëren eerst zodat de invoer beschikbaar blijft. doel.parentkiest de doelmap.mkdirmaakt die aan;parents=Truemaakt tussenliggende mappen enexist_ok=Trueaccepteert een al bestaande map.
st_mtimeis de wijzigingsdatum.strftimezet deze om naar een jaar en een maand met twee cijfers.mkdir(parents=True, exist_ok=True)maakt ook ontbrekende bovenliggende mappen aan.copy2kopieert de inhoud en probeert bestandsmetadata te behouden. De mapkeuze is op bestandsdatum gebaseerd; een gekopieerde download kan daardoor in een andere maand staan dan verwacht.
De notatie tekst_a if voorwaarde else tekst_b kiest één van twee waarden. In de laatste print kiest het script zo een melding voor de testmodus of voor het echte kopiëren. Dit is de korte vorm van de bekende if/else-keuze.
05 - Een gerichte AI-prompt maken
Geef AI eerst een concrete opdracht. Kopieer bijvoorbeeld deze prompt en vergelijk het antwoord met de voorbeeldcode in het volgende blok:
Maak een script met pathlib, datetime en shutil dat JPG-, JPEG- en PNG-
bestanden direct in invoer op wijzigingsdatum indeelt in
gesorteerd/jaar/maand. Gebruik TESTMODUS = True om alleen bron en doel te
tonen. Kopieer bij False met copy2, behoud originelen en sla bestaande
doelen over. Sla symbolische links over en meld fouten per bestand. Gebruik
geen EXIF in deze eerste versie.
Vraag om uitleg bij onbekende regels en controleer welke bestanden de code leest en schrijft voordat je haar uitvoert. Gebruik de oefengegevens uit dit project.
06 - Een werkende basisversie
Dit is een complete basisversie voor fotos_sorteren.py. Neem de code over of vergelijk haar met het antwoord van AI.
from pathlib import Path
from datetime import datetime
import shutil
BASIS = Path(__file__).resolve().parent
INVOER = BASIS / "invoer"
UITVOER = BASIS / "gesorteerd"
TESTMODUS = True
def main():
if not INVOER.is_dir():
print(f"Map ontbreekt: {INVOER}")
return
for bron in sorted(INVOER.iterdir()):
if bron.is_symlink() or not bron.is_file():
continue
if bron.suffix.lower() not in {".jpg", ".jpeg", ".png"}:
continue
try:
datum = datetime.fromtimestamp(bron.stat().st_mtime)
doel = UITVOER / datum.strftime("%Y") / datum.strftime("%m") / bron.name
if doel.exists():
print(f"Overgeslagen, bestaat al: {doel}")
continue
print(f"{bron.name} -> {doel.relative_to(BASIS)}")
if not TESTMODUS:
doel.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(bron, doel)
except OSError as fout:
print(f"Fout bij {bron.name}: {fout}")
print("Testmodus: geen kopieën gemaakt." if TESTMODUS else "Kopiëren klaar.")
if __name__ == "__main__":
main()
07 - Het script uitvoeren
- Sla de volledige code op als
fotos_sorteren.pyin je projectmap. Zet eventuele invoerbestanden op de plek die in blok 03 staat. - Open de geïntegreerde terminal in die projectmap en activeer
.venvals dat nog niet is gebeurd. - Voer het script uit met:
python fotos_sorteren.py
Lees eerst de terminaluitvoer en open daarna eventuele uitvoerbestanden. Controleer het resultaat met blok 08 voordat je met eigen gegevens verdergaat.
08 - Het resultaat controleren
- In testmodus verschijnt alleen het plan en wordt
gesorteerdnog niet aangemaakt. - Zet
TESTMODUS = False: de kopieën staan onder het jaar en de maand van hun wijzigingsdatum. De originelen staan nog ininvoer. - Voer opnieuw uit: bestaande doelen worden overgeslagen. Voeg een tekstbestand toe: dat wordt niet gekopieerd.
09 - Fouten herkennen en oplossen
- Alle foto’s staan in dezelfde maand? Ze kunnen dezelfde wijzigingsdatum hebben. Vergelijk de bestandseigenschappen.
- Een onjuist fotobestand wordt toch gekopieerd? Dit script filtert op extensie en controleert de afbeeldingsinhoud niet.
10 - Uitbreiden en afronden
Probeer deze vervolgstap pas als de basis werkt:
Vraag AI om per jaar en maand te tellen hoeveel foto’s worden gekopieerd en dat in een CSV op te slaan. CSV schrijven ken je uit project A. Laat de testmodus dezelfde telling tonen zonder bestanden te kopiëren en controleer dat bestaande doelen niet opnieuw meetellen.
Bewaar je werkende basisversie en verander één onderdeel tegelijk. Geef AI bij een fout de foutmelding, het relevante stukje code, je testinvoer en de verwachte uitkomst.
Het project is afgerond wanneer de basiscontrole uit blok 08 slaagt en je in eigen woorden kunt uitleggen welke invoer wordt gebruikt, hoe de verwerking werkt en waar de uitvoer terechtkomt.