Project C - Zoek dubbele bestanden
01 - Projectoverzicht
- In dit project maak je een Python-script dat dubbele bestanden opspoort in een map.
- Het script helpt wanneer dezelfde foto's, downloads of documenten op meerdere plekken zijn opgeslagen.
- Je gebruikt een testmap met enkele bestanden die expres dubbel zijn gekopieerd.
- Het script vergelijkt bestanden eerst op bestandsgrootte en daarna op inhoud met een hash.
- Het resultaat is een lijst met groepen bestanden die waarschijnlijk exact gelijk zijn.
- Je gebruikt AI om het script stap voor stap te laten genereren, zonder dat bestanden automatisch worden verwijderd.
- Je voert de code uit in VS Code en bekijkt welke dubbele bestanden in de terminal worden genoemd.
- Als AI te snel bestanden wil verwijderen, verbeter je de prompt zodat het script alleen rapporteert en niets wist.
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_cen open die map in VS Code. Maak daarin straksdubbele_bestanden.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 origineel.txt met de tekst appel. Kopieer dit bestand als kopie.txt. Maak anders.txt met de tekst peren: evenveel tekens, andere inhoud. Gebruik dezelfde tekstcodering en regeleinden. Zet een derde kopie in de submap archief.
04 - Begrippen en hulpmiddelen vóór de opdracht
- hashlib berekent een vingerafdruk van bytes.
sha256()begint de berekening,update()verwerkt een blok enhexdigest()geeft het resultaat als tekst. "rb"opent een bestand voor binaire invoer: ruwe bytes, geen gedecodeerde tekst.b""is de lege byteswaarde die het einde van het bestand aangeeft.defaultdict(list)is een dictionary uitcollectionsdie automatisch een lege lijst maakt voor een nieuwe sleutel. Zo verzamelen we paden per grootte en daarna per hash.os.walkdoorloopt mappen. Per ronde krijg je de huidige mapnaam, submapnamen en bestandsnamen.onerrorgeeft fouten door aan onze meldfunctie. Metmappen[:]passen we de lijst ter plekke aan, zodat links niet worden bezocht.- De lijstcomprehensie voor submappen is de korte lusnotatie uit hoofdstuk 4.
relative_to(INVOER)toont een pad vanaf de invoermap.
- Bestanden met een verschillende grootte kunnen niet exact dezelfde inhoud hebben. De eerste selectie voorkomt onnodig leeswerk.
- Een hash is een berekende vingerafdruk van de inhoud. Gelijke SHA-256-hashes zijn een zeer sterke aanwijzing voor identieke inhoud; de bestandsnaam speelt daarbij geen rol.
- Blokken lezen voorkomt dat een groot bestand in één keer in het geheugen moet. Scan een map waarin tijdens de controle niets wordt gewijzigd.
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:
Schrijf een beginnersscript dat invoer inclusief submappen doorzoekt op
dubbele bestanden. Groepeer eerst op grootte en bereken alleen voor groepen
met meer dan één bestand een SHA-256-hash, in blokken van 65536 bytes. Sla
symbolische links over, meld leesfouten en toon groepen met gelijke grootte
en hash. Rapporteer alleen, verwijder of verplaats niets. Gebruik pathlib,
os.walk en hashlib.
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 dubbele_bestanden.py. Neem de code over of vergelijk haar met het antwoord van AI.
from pathlib import Path
from collections import defaultdict
import hashlib
import os
INVOER = Path(__file__).resolve().parent / "invoer"
def meld_fout(fout):
print(f"Niet leesbaar: {fout}")
def bereken_hash(pad):
hasher = hashlib.sha256()
with pad.open("rb") as bestand:
while True:
blok = bestand.read(65536)
if blok == b"":
break
hasher.update(blok)
return hasher.hexdigest()
def main():
if not INVOER.is_dir():
print(f"Map ontbreekt: {INVOER}")
return
op_grootte = defaultdict(list)
for mapnaam, mappen, namen in os.walk(INVOER, onerror=meld_fout):
mappen[:] = sorted(m for m in mappen if not (Path(mapnaam) / m).is_symlink())
for naam in sorted(namen):
pad = Path(mapnaam) / naam
try:
if not pad.is_symlink() and pad.is_file():
op_grootte[pad.stat().st_size].append(pad)
except OSError as fout:
meld_fout(fout)
groepen = 0
for grootte, paden in op_grootte.items():
if len(paden) < 2:
continue
op_hash = defaultdict(list)
for pad in paden:
try:
op_hash[bereken_hash(pad)].append(pad)
except OSError as fout:
meld_fout(fout)
for dubbelen in op_hash.values():
if len(dubbelen) > 1:
groepen += 1
print(f"Groep {groepen}: {grootte} bytes per bestand")
for pad in dubbelen:
print(f" {pad.relative_to(INVOER)}")
print(f"Aantal groepen: {groepen}. Er is niets verwijderd.")
if __name__ == "__main__":
main()
07 - Het script uitvoeren
- Sla de volledige code op als
dubbele_bestanden.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 dubbele_bestanden.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
- Je ziet één groep met
origineel.txt,kopie.txtenarchiefmet de derde kopie. anders.txtkomt niet in de groep, ook wanneer de bestandsgrootte gelijk is.- Wijzig de inhoud van
kopie.txten start opnieuw. Alleen de twee ongewijzigde exemplaren blijven in dezelfde groep.
09 - Fouten herkennen en oplossen
- Geen duplicaten? Controleer of de kopieën echt dezelfde inhoud hebben, inclusief regeleinden.
- Een melding over toegang? Het bestand of de map is overgeslagen. Het overzicht kan daardoor onvolledig zijn.
10 - Uitbreiden en afronden
Probeer deze vervolgstap pas als de basis werkt:
Laat AI per groep berekenen hoeveel bytes de extra exemplaren innemen: (aantal - 1) × grootte. Vraag om export naar CSV, zonder een verwijderfunctie.
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.