Rozdział 23 · Część IV · Wdrażamy SafeSort

Zeskanuj katalog

scan() czyta system plików ściśle — przechodzi przez katalog rekurencyjnie i nie zmienia ani jednego pliku.

SafeSort · Część 4 z 6Wdrożenie
GitHubIssue #1 · Project SafeSort Pierwsze wydanie
Add directory scanner
Area: FilesystemPriority: High
git switch -c feat/directory-scanner

Pierwszy krok SafeSort — przejrzeć katalog i sporządzić lista plików. Funkcja scan() — jedna z trzech komend wyłącznie odczytujących SafeSort: ona tylko wywołuje iterdir() oraz stat(), Nigdy nie tworząc, nie przenosząc ani nie usuwając niczego z dysku.

Downloads/
report.pdf
cat.jpg
archive.zip
System plikówkatalog z plikamiScannerscan()FileInfotak, rozmiar,rozszerzenie
Ten łańcuch będzie rósł: następne strony dodadzą do niego nowe ogniwa.
src/safesort/scanner.py
def scan(root: Path, config: Config) -> list[FileInfo]:
    root = Path(root)
    excluded = config.excluded_names()
    results: list[FileInfo] = []
    _scan_dir(root, excluded, results)
    return results

Samo przejście jest rekurencyjne: _scan_dir() wchodzi w każdy podkatalog i nazywa się ponownie:

src/safesort/scanner.py
for entry in entries:
    if entry.is_symlink():
        continue  # symboliczne linki pominięte – zobacz następną stronę
    if entry.is_dir():
        if entry.name in excluded:
            continue  # Katalogi wykluczone są pomijane – zobacz następną stronę
        _scan_dir(entry, excluded, results)
    elif entry.is_file():
        size = entry.stat().st_size
        results.append(FileInfo(path=entry, size=size, extension=entry.suffix.lower()))
Katalog, którego nie można odczytać, nie powinien zatrzymywać całego skanowania
Jeśli nie ma wystarczających praw dostępu do podkatalogu, iterdir() przyczyny PermissionError. Implementacja _scan_dir() przechwytuje ten błąd dla każdego podkatalogu osobno, zapisuje ostrzeżenie w dzienniku i kontynuuje skanowanie pozostałych katalogów — dzięki temu jeden niedostępny podkatalog nie przerywa całego przeglądu. Później omówimy to szczegółowo wraz z innymi błędami systemu plików.

Skaner można sprawdzić teraz — rzeczywisty wydruk:

~/safesort $ safesort scan ~/Downloads
Files scanned: 9
Documents: 3
Images: 1
Archives: 1
Other: 4

Punkt kontrolny testu: Wymagania stają się regresją

tests/test_scanner.py
def test_scan_finds_file_without_changing_it(tmp_path):
    source = tmp_path / "report.pdf"
    source.write_bytes(b"report")

    files = scan(tmp_path, Config())

    assert [item.path for item in files] == [source]
    assert source.read_bytes() == b"report"

Najpierw wymaganie jest obserwowane na jednym przykładzie, następnie test zapisuje je jako kontrakt. Późniejsza sekcja testowania rozszerzy tę podstawę fixtures i edge cases.

Praktyka: Skanowanie prawdziwego katalogu
Potrzebny jest dostęp do prawdziwego systemu plików – uruchamianego lokalnie w VS Code, PyCharm lub Jupyter
Praktyka kursuje lokalnie
Otwórz praktykę →