Batu Lab NotesPractical developer guides

Keep a local project scan inside its intended directory tree

By Batu ยท English technical notes

Also published in our Blogger archive.

Direct answer

A project scanner should choose its traversal boundary before it begins reading entries. Path.is_symlink() lets this example skip a directory entry that points outside the temporary root. The normal case reports only inside.py; the symbolic-link branch is either skipped or, on platforms where links cannot be created, reported as unavailable rather than silently followed.

A symlink is the relevant edge case because a lexical path under project/ can resolve to another tree. Filtering the entry before recursion is simpler to review than discovering the escape after files have already been visited.

This snippet is intentionally shallow: it does not recursively walk directories, resolve hard links, or establish a sandbox against hostile filesystem races. For a broader scanner, maintain a no-follow rule at every descent and record skipped paths in a non-sensitive form. The example only demonstrates the policy for one directory entry.

Complete example

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as directory:
    root = Path(directory) / "project"
    outside = Path(directory) / "outside"
    root.mkdir()
    outside.mkdir()
    (root / "inside.py").write_text("x", encoding="utf-8")
    (outside / "secret.py").write_text("x", encoding="utf-8")
    link = root / "linked"
    try:
        link.symlink_to(outside, target_is_directory=True)
    except OSError:
        skipped = "symlink-unavailable"
    else:
        visible = [item.name for item in root.iterdir() if not item.is_symlink()]
        assert visible == ["inside.py"]
        skipped = "symlink-skipped"
    print(f"files=1 {skipped}")

Expected stdout:

files=1 symlink-skipped

Sources

- pathlib documentation

Prepared with AI assistance. The example uses synthetic data; its stated limits apply.