Przechodzenie po katalogach i wyszukiwanie plików
os.walk(), wzorce glob oraz filtrowanie plików według typu lub daty.
Przechodzenie po katalogach i wyszukiwanie plików to bezpłatna lekcja AI Agents na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Agents, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Agents zawiera 4 lekcji w sumie.
Dlaczego agenty potrzebują przeszukiwania katalogów
Agenty często muszą znajdować pliki spełniające określone kryteria — wszystkie pliki Pythona w bazie kodu, wszystkie pliki CSV w katalogu danych lub wszystkie najnowsze dzienniki. Python udostępnia trzy główne narzędzia: os.walk(), Path.iterdir() i Path.rglob(). Każde z nich ma inne zalety, zależnie od wymaganej głębokości wyszukiwania.
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() — rekurencyjne przeszukiwanie katalogów
os.walk(root) zwraca krotkę (dirpath, dirnames, filenames) dla każdego katalogu w drzewie. Jest to klasyczne podejście Pythona do rekurencyjnego przeszukiwania katalogów, zapewniające szczegółową kontrolę nad tym, do których podkatalogów należy wejść.
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() — wyświetlanie jednego poziomu
Path.iterdir() wyświetla bezpośrednią zawartość katalogu — nie przeszukuje podkatalogów rekurencyjnie. Należy go używać, gdy potrzebne są tylko bezpośrednie elementy podrzędne katalogu i nie ma potrzeby schodzenia głębiej.
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() — rekurencyjne wyszukiwanie według wzorca
Path.rglob(pattern) rekurencyjnie wyszukuje wszystkie pliki pasujące do wzorca glob. Jest to najbardziej zwięzły sposób znajdowania wszystkich plików danego typu w dowolnym miejscu drzewa katalogów. ** we wzorcu glob oznacza „dowolną liczbę katalogów”.
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() — dopasowywanie wzorców
glob.glob(pattern, recursive=True) to tradycyjny interfejs glob. Po ustawieniu recursive=True symbol wieloznaczny ** dopasowuje dowolną ścieżkę podkatalogu. Funkcja zwraca ciągi znaków, natomiast pathlib.rglob zwraca obiekty 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')Filtrowanie według rozszerzenia pliku
Podczas przeszukiwania katalogów należy filtrować pliki według rozszerzenia za pomocą Path.suffix (które zawiera kropkę, na przykład '.py') lub sprawdzać rozszerzenie względem zbioru dozwolonych rozszerzeń. W przypadku filtrowania według wielu rozszerzeń jest to szybsze i dokładniejsze niż wzorce 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')Filtrowanie według rozmiaru pliku
Agenty czasami muszą znajdować pliki powyżej lub poniżej określonego progu rozmiaru — pomijać małe, puste pliki albo unikać przetwarzania ogromnych plików, które mogłyby przeciążyć pamięć. Rozmiar pliku w bajtach można uzyskać za pomocą Path.stat().st_size.
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)}')Filtrowanie według czasu modyfikacji
Agenty w potokach przyrostowych muszą przetwarzać tylko pliki, które zmieniły się od czasu ostatniego uruchomienia. Aby znaleźć ostatnio zmodyfikowane pliki, należy użyć stat().st_mtime (czasu modyfikacji w postaci znacznika czasu Unix).
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")}')Pomijanie ukrytych plików i katalogów systemowych
Podczas przeszukiwania repozytoriów kodu lub katalogów użytkowników należy pomijać ukryte pliki (zaczynające się od .) oraz katalogi systemowe, takie jak .git, __pycache__, node_modules i .venv. Zawierają one tysiące plików, które w przypadku większości agentów są nieistotne.
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')Tworzenie inwentarza plików
Inwentarz plików to uporządkowane podsumowanie drzewa katalogów — przydatne w przypadku agentów, które muszą zaplanować pracę przed rozpoczęciem przetwarzania. Należy zebrać nazwę, ścieżkę, rozmiar, rozszerzenie i czas modyfikacji na liście słowników, którą można serializować do formatu 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')Monitorowanie katalogu pod kątem zmian
Niektóre agenty muszą reagować na pojawianie się nowych plików w katalogu. Chociaż w środowisku produkcyjnym najlepiej sprawdza się pełna biblioteka do monitorowania plików, taka jak watchdog, prostym rozwiązaniem jest okresowe skanowanie katalogu i porównywanie wyników ze znanym zbiorem plików.
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)
Szybki test: rglob a iterdir
Sprawdź swoją znajomość metod przeszukiwania katalogów.
Podsumowanie przeszukiwania katalogów
Możesz teraz znaleźć każdy plik potrzebny agentowi:
- os.walk() — pełna kontrola nad rekurencyjnym przeszukiwaniem; aby pominąć podkatalogi, modyfikuj
dirnamesbezpośrednio - Path.iterdir() — wyświetlanie jednego poziomu bezpośrednich elementów podrzędnych
- Path.rglob('*.ext') — najbardziej przejrzyste rekurencyjne wyszukiwanie według wzorca
- glob.glob('**/*.ext', recursive=True) — tradycyjna alternatywa zwracająca ciągi znaków
- Filtruj według
.suffixw przypadku rozszerzenia,.stat().st_sizew przypadku rozmiaru i.stat().st_mtimew przypadku czasu modyfikacji - Zawsze pomijaj ukryte pliki i katalogi systemowe, takie jak
.gitinode_modules
Często zadawane pytania
Czy lekcja „Przechodzenie po katalogach i wyszukiwanie plików” jest bezpłatna?
Tak — pełny tekst „Przechodzenie po katalogach i wyszukiwanie plików” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Agents, przejdź na CoddyKit PRO. Kurs AI Agents zawiera 4 lekcji w sumie.
Co nauczysz się w „Przechodzenie po katalogach i wyszukiwanie plików”?
os.walk(), wzorce glob oraz filtrowanie plików według typu lub daty. Ćwiczysz AI Agents z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Agents?
Nie wymagamy żadnego doświadczenia. AI Agents w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Przechodzenie po katalogach i wyszukiwanie plików”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Agents?
Tak. Każda lekcja AI Agents zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Odczyt i zapis plików w kontekście agenta
- Przechodzenie po katalogach i wyszukiwanie plików
- Obsługa formatów plików: CSV, JSON i TXT
- Bezpieczne operacje na plikach z obsługą błędów