Walk a project tree without following directory symlinks
Direct answer
os.walk(root, followlinks=False) avoids descending through directory symlinks. The example also removes symlink entries from the mutable directory list before descent, making its exclusion policy explicit. A regular src directory is traversed; vendor-link, which points to a separate temporary tree, is skipped.
The assertion checks the relative paths actually observed. Seeing only src/main.py confirms that the synthetic outside file was not included in this walk. Relative paths keep the result independent of the temporary directory name.
This example requires permission to create a symlink. Its expected output describes the successful symlink setup; if the platform rejects that operation, it prints symlink=unavailable instead. That is an unsupported fixture, not a successful traversal test. The rule also says nothing about symlinks to individual files or filesystem changes during a scan. Apply a separate file-opening policy before reading discovered content; a traversal option does not create a security sandbox.
Complete example
import os
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
root = Path(directory) / "project"
outside = Path(directory) / "outside"
(root / "src").mkdir(parents=True)
outside.mkdir()
(root / "src" / "main.py").write_text("pass\n", encoding="utf-8")
(outside / "secret.py").write_text("secret = 1\n", encoding="utf-8")
try:
(root / "vendor-link").symlink_to(outside, target_is_directory=True)
except OSError:
print("symlink=unavailable")
else:
seen = []
for current, directories, names in os.walk(root, followlinks=False):
for name in directories[:]:
if (Path(current) / name).is_symlink():
directories.remove(name)
seen.extend((Path(current) / name).relative_to(root).as_posix() for name in names)
assert seen == ["src/main.py"]
print("files=src/main.py skipped=vendor-link")
Expected stdout (for a platform supporting the demonstrated operation):
files=src/main.py skipped=vendor-link
Sources
- os.walk
Prepared with AI assistance. The example uses synthetic data; its stated limits apply.
Comments
Post a Comment