Een directory doorzoeken

Deze pagina bevat uitvoerbare code.

Opdracht: Een directory doorzoeken

De gegeven code uit het werkcollege:

documents = {
    "naam": "documenten",
    "bestanden": {"verslag.docx": 120, "rooster.pdf": 300},
    "directories": [
        {
            "naam": "projecten",
            "bestanden": {"plan.docx": 40, "logo.png": 500},
            "directories": [
                {
                    "naam": "archief",
                    "bestanden": {"notulen.docx": 25, "setup.exe": 900},
                    "directories": [],
                },
            ],
        },
        {
            "naam": "foto's",
            "bestanden": {"strand.jpg": 2000, "berg.jpg": 1800},
            "directories": [],
        },
        {"naam": "leeg", "bestanden": {}, "directories": []},
    ],
}

EMPTY = {"naam": "leeg", "bestanden": {}, "directories": []}
PROJECTS = documents["directories"][0]

Stap 1: count_files(d)

def count_files(d):
    """Geeft het aantal bestanden in d en in al zijn subdirectories."""
    n = len(d["bestanden"])

    for sub in d["directories"]:
        n = n + count_files(sub)

    return n


assert count_files(documents) == 8
assert count_files(PROJECTS) == 4
assert count_files(EMPTY) == 0

Stap 2: total_size(d)

def total_size(d):
    """Geeft de totale grootte van de bestanden in d en al zijn subdirectories."""
    return sum(d["bestanden"].values()) + sum(
        [total_size(sub) for sub in d["directories"]]
    )


assert total_size(documents) == 5685
assert total_size(PROJECTS) == 1465
assert total_size(EMPTY) == 0

Stap 3: safe_name(name)

Het basisgeval is de lege naam, en die is veilig. De recursie stopt eerder zodra er een verkeerd teken staat.

from string import ascii_letters, digits

SAFE_CHARS = ascii_letters + digits + "._-"


def safe_name(name):
    """Geeft True als name alleen letters, cijfers, punten, _ en - bevat."""
    if name == "":
        return True
    elif name[-1] not in SAFE_CHARS:
        return False
    else:
        return safe_name(name[:-1])


assert safe_name("verslag.docx") == True
assert safe_name("data_2024-01.csv") == True
assert safe_name("foto's") == False
assert safe_name("mijn cv.pdf") == False
assert safe_name("") == True
assert safe_name("café.txt") == False

Stap 4: unsafe_names(d)

def unsafe_names(d):
    """Geeft de namen in d en zijn subdirectories die niet veilig zijn."""
    result = [name for name in d["bestanden"] if not safe_name(name)]

    for sub in d["directories"]:
        if not safe_name(sub["naam"]):
            result = result + [sub["naam"]]
        result = result + unsafe_names(sub)

    return result


WORK = {
    "naam": "mijn werk",
    "bestanden": {"cv.pdf": 10, "brief 1.docx": 5},
    "directories": [
        {"naam": "oude versies", "bestanden": {"a:b.txt": 1}, "directories": []},
    ],
}

assert unsafe_names(documents) == ["foto's"]
assert unsafe_names(WORK) == ["brief 1.docx", "oude versies", "a:b.txt"]
assert unsafe_names(EMPTY) == []

Stap 5: depth(d)

def depth(d):
    """Geeft het aantal niveaus van d: 1 voor een directory zonder subdirectories."""
    deepest = 0

    for sub in d["directories"]:
        sub_depth = depth(sub)
        if sub_depth > deepest:
            deepest = sub_depth

    return 1 + deepest


assert depth(documents) == 3
assert depth(PROJECTS) == 2
assert depth(EMPTY) == 1