Attraversamento delle directory e ricerca dei file
os.walk(), pattern glob e filtraggio dei file per tipo o data
Attraversamento delle directory e ricerca dei file è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.
Perché gli agenti devono attraversare le directory
Gli agenti devono spesso trovare file che soddisfano determinati criteri: tutti i file Python in una codebase, tutti i file CSV in una directory di dati oppure tutti i log recenti. Python offre tre strumenti principali: os.walk(), Path.iterdir() e Path.rglob(). Ognuno presenta vantaggi diversi, a seconda della profondità della ricerca necessaria.
import os
from pathlib import Path
# Count all files in a directory tree
root = Path('/tmp/agent_workspace')
file_count = sum(1 for f in root.rglob('*') if f.is_file())
print(f'Found {file_count} files under {root}')os.walk() — Attraversamento ricorsivo delle directory
os.walk(root) restituisce una tupla di (dirpath, dirnames, filenames) per ogni directory dell'albero. È l'approccio classico di Python per l'attraversamento ricorsivo e offre un controllo dettagliato sulle sottodirectory da attraversare.
import os
import tempfile
# --- demo setup: build a small project tree so the walk has something to show ---
root = tempfile.mkdtemp(prefix='project_')
os.makedirs(os.path.join(root, 'src'), exist_ok=True)
os.makedirs(os.path.join(root, '.git'), exist_ok=True)
with open(os.path.join(root, 'README.md'), 'w') as f:
f.write('demo')
with open(os.path.join(root, 'src', 'main.py'), 'w') as f:
f.write('print(1)')
for dirpath, dirnames, filenames in os.walk(root):
# Skip hidden directories (like .git)
dirnames[:] = [d for d in dirnames if not d.startswith('.')]
print(f'In directory: {dirpath}')
print(f' Subdirs: {dirnames}')
print(f' Files: {filenames}')
for filename in filenames:
full_path = os.path.join(dirpath, filename)
print(f' File: {full_path}')
Path.iterdir() — Elenco di un singolo livello
Path.iterdir() elenca il contenuto immediato di una directory: non attraversa ricorsivamente le sottodirectory. Lo utilizzi quando servono solo gli elementi direttamente contenuti in una directory e si vuole evitare di scendere a livelli più profondi.
from pathlib import Path
data_dir = Path('data')
data_dir.mkdir(exist_ok=True)
(data_dir / 'a.csv').write_text('x')
(data_dir / 'sub').mkdir(exist_ok=True)
for item in data_dir.iterdir():
if item.is_file():
print(f'FILE: {item.name} ({item.stat().st_size} bytes)')
elif item.is_dir():
print(f'DIR: {item.name}/')
csv_files = [f for f in data_dir.iterdir()
if f.is_file() and f.suffix == '.csv']
print(f'Found {len(csv_files)} CSV files')Path.rglob() — Glob ricorsivo
Path.rglob(pattern) trova ricorsivamente tutti i file che corrispondono a un pattern glob. È il modo più conciso per trovare tutti i file di un determinato tipo in qualsiasi punto di un albero di directory. In glob, ** significa "un numero qualsiasi di directory".
from pathlib import Path
project = Path('/tmp/my_project')
# Find all Python files recursively
python_files = list(project.rglob('*.py'))
print(f'Found {len(python_files)} Python files:')
for f in python_files:
print(f' {f.relative_to(project)}')
# Find all JSON files
json_files = list(project.rglob('*.json'))
# Find files matching a name pattern
test_files = list(project.rglob('test_*.py'))
print(f'Found {len(test_files)} test files')glob.glob() — Corrispondenza dei pattern
glob.glob(pattern, recursive=True) è l'interfaccia glob tradizionale. Con recursive=True, il carattere jolly ** corrisponde a qualsiasi percorso di sottodirectory. Restituisce stringhe, mentre pathlib.rglob restituisce oggetti Path.
import glob
# Find all CSV files recursively
csv_files = glob.glob('data/**/*.csv', recursive=True)
print(f'Found {len(csv_files)} CSV files')
for f in csv_files:
print(f' {f}')
# Find all log files in a specific directory (non-recursive)
logs = glob.glob('/var/log/*.log')
# Find files matching multiple criteria
import fnmatch
all_files = glob.glob('/tmp/**/*', recursive=True)
config_files = [
f for f in all_files
if fnmatch.fnmatch(f, '*.yaml') or fnmatch.fnmatch(f, '*.yml')
]
print(f'Found {len(config_files)} YAML config files')Filtraggio per estensione del file
Durante l'attraversamento delle directory, filtri i file in base alla loro estensione utilizzando Path.suffix (che include il punto, ad esempio '.py') oppure verificandola rispetto a un insieme di estensioni consentite. Per il filtraggio su più estensioni, questo è più rapido e preciso dei pattern glob.
from pathlib import Path
directory = Path('/tmp/mixed_files')
ALLOWED_EXTENSIONS = {'.py', '.js', '.ts', '.json', '.yaml'}
# Filter by allowed extensions
code_files = [
f for f in directory.rglob('*')
if f.is_file() and f.suffix.lower() in ALLOWED_EXTENSIONS
]
print(f'Found {len(code_files)} code/config files')
# Group files by extension
from collections import defaultdict
by_ext = defaultdict(list)
for f in directory.rglob('*'):
if f.is_file():
by_ext[f.suffix].append(f)
for ext, files in sorted(by_ext.items()):
print(f'{ext}: {len(files)} files')Filtraggio per dimensione del file
A volte gli agenti devono trovare file al di sopra o al di sotto di una determinata soglia di dimensione: per esempio, ignorare piccoli file vuoti o evitare di elaborare file enormi che saturerebbero la memoria. Utilizzi Path.stat().st_size per ottenere la dimensione del file in byte.
from pathlib import Path
data_dir = Path('/tmp/data')
MIN_SIZE = 1024 # 1 KB — skip empty/tiny files
MAX_SIZE = 50_000_000 # 50 MB — skip very large files
processable = []
skipped_small = []
skipped_large = []
for f in data_dir.rglob('*.json'):
if not f.is_file():
continue
size = f.stat().st_size
if size < MIN_SIZE:
skipped_small.append(f.name)
elif size > MAX_SIZE:
skipped_large.append(f.name)
else:
processable.append(f)
print(f'Processable: {len(processable)}')
print(f'Too small: {len(skipped_small)}')
print(f'Too large: {len(skipped_large)}')Filtraggio per data di modifica
Negli agenti che operano in pipeline incrementali è necessario elaborare solo i file modificati dall'ultima esecuzione. Utilizzi stat().st_mtime (la data di modifica espressa come timestamp Unix) per trovare i file modificati di recente.
from pathlib import Path
import time
import datetime
data_dir = Path('/tmp/data')
# Files modified in the last 24 hours
cutoff = time.time() - (24 * 60 * 60)
recent_files = [
f for f in data_dir.rglob('*.log')
if f.is_file() and f.stat().st_mtime > cutoff
]
print(f'Modified in last 24h: {len(recent_files)} files')
# Sort by modification time (newest first)
recent_files.sort(key=lambda f: f.stat().st_mtime, reverse=True)
for f in recent_files[:5]: # top 5 most recent
mtime = datetime.datetime.fromtimestamp(f.stat().st_mtime)
print(f' {f.name}: {mtime.strftime("%Y-%m-%d %H:%M:%S")}')Esclusione dei file nascosti e delle directory di sistema
Quando attraversa repository di codice o directory degli utenti, escluda i file nascosti (che iniziano con .) e directory di sistema come .git, __pycache__, node_modules e .venv. Contengono migliaia di file irrilevanti per la maggior parte degli agenti.
from pathlib import Path
SKIP_DIRS = {'.git', '__pycache__', 'node_modules', '.venv',
'.env', 'dist', 'build', '.mypy_cache'}
def iter_source_files(root, extensions):
root = Path(root)
for path in root.rglob('*'):
# Skip if any parent is in SKIP_DIRS
if any(part in SKIP_DIRS for part in path.parts):
continue
# Skip hidden files
if path.name.startswith('.'):
continue
if path.is_file() and path.suffix in extensions:
yield path
python_files = list(iter_source_files('/tmp/project', {'.py'}))
print(f'Found {len(python_files)} Python source files')Creazione di un inventario dei file
Un inventario dei file è un riepilogo strutturato di un albero di directory, utile per gli agenti che devono pianificare il lavoro prima dell'elaborazione. Raccolga nome, percorso, dimensione, estensione e data di modifica in un elenco di dict che possa essere serializzato in JSON.
from pathlib import Path
import datetime
import json
def build_inventory(root_dir, pattern='**/*'):
root = Path(root_dir)
inventory = []
for f in root.glob(pattern):
if not f.is_file():
continue
stat = f.stat()
inventory.append({
'name': f.name,
'path': str(f.relative_to(root)),
'extension': f.suffix,
'size_bytes': stat.st_size,
'modified': datetime.datetime.fromtimestamp(
stat.st_mtime
).isoformat()
})
return sorted(inventory, key=lambda x: x['path'])
inventory = build_inventory('/tmp/data')
with open('file_inventory.json', 'w') as out:
json.dump(inventory, out, indent=2)
print(f'Inventoried {len(inventory)} files')Monitoraggio delle modifiche in una directory
Alcuni agenti devono reagire alla comparsa di nuovi file in una directory. Sebbene una libreria completa per il monitoraggio dei file come watchdog sia la scelta migliore in produzione, un approccio semplice consiste nell'analizzare periodicamente la directory e confrontare il risultato con un insieme noto di file.
from pathlib import Path
import time
def watch_for_new_files(watch_dir, extension='.json', interval=5):
watch_dir = Path(watch_dir)
known_files = set(watch_dir.glob(f'*{extension}'))
print(f'Watching {watch_dir} for new {extension} files...')
while True:
time.sleep(interval)
current_files = set(watch_dir.glob(f'*{extension}'))
new_files = current_files - known_files
for f in new_files:
print(f'New file detected: {f.name}')
process_new_file(f) # handle the new file
known_files = current_files
def process_new_file(file_path):
print(f'Processing: {file_path}')
# --- demo (one polling cycle, without the infinite while True loop) ---
import tempfile
demo_dir = Path(tempfile.mkdtemp())
known_files = set(demo_dir.glob('*.json'))
print(f'Watching {demo_dir} for new .json files...')
(demo_dir / 'result_a.json').write_text('{}', encoding='utf-8')
(demo_dir / 'result_b.json').write_text('{}', encoding='utf-8')
current_files = set(demo_dir.glob('*.json'))
new_files = current_files - known_files
for f in sorted(new_files, key=lambda p: p.name):
print(f'New file detected: {f.name}')
process_new_file(f)
Verifica rapida: rglob e iterdir
Verifichi la propria comprensione dei metodi di attraversamento delle directory.
Riepilogo dell'attraversamento delle directory
Ora è in grado di trovare qualsiasi file necessario al suo agente:
- os.walk() — controllo completo sull'attraversamento ricorsivo; modifichi
dirnamesdirettamente per escludere le sottodirectory - Path.iterdir() — elenco di un singolo livello degli elementi direttamente contenuti
- Path.rglob('*.ext') — ricerca ricorsiva più chiara tramite pattern
- glob.glob('**/*.ext', recursive=True) — alternativa tradizionale che restituisce stringhe
- Filtri con
.suffixper l'estensione,.stat().st_sizeper la dimensione e.stat().st_mtimeper la data di modifica - Escluda sempre i file nascosti e le directory di sistema come
.gitenode_modules
Domande Frequenti
La lezione «Attraversamento delle directory e ricerca dei file» è gratuita?
Sì — il testo completo di «Attraversamento delle directory e ricerca dei file» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.
Cosa imparerò in «Attraversamento delle directory e ricerca dei file»?
os.walk(), pattern glob e filtraggio dei file per tipo o data Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Agents?
Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Attraversamento delle directory e ricerca dei file»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Agents?
Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Lettura e scrittura dei file nel contesto degli agenti
- Attraversamento delle directory e ricerca dei file
- Gestione dei formati file: CSV, JSON e TXT
- Operazioni sicure sui file con gestione degli errori