Python pathlib.Path.info provides an efficient way to inspect what a path represents, including whether it is a file, directory, symbolic link, or another kind of filesystem entry. It is particularly useful in directory scanners, backup tools, project indexers, data pipelines, build systems, and applications that classify many paths without repeating expensive operating-system calls.
The key idea is reuse. When directory iteration has already obtained basic metadata for an entry, Python may keep that information available through the path information object. Your code can then ask several related questions without always performing a fresh stat operation. The result is a clear object-oriented API and, for large trees, potentially better performance.
What pathlib.Path.info represents
Path.info groups queries about path existence and type. It belongs to a Path object and fits naturally with the rest of pathlib. Instead of mixing os.path, manual stat calls, and platform-specific conditions, you can keep classification logic close to the path itself.
The feature is most valuable after directory iteration. On many systems, listing a directory already returns enough metadata to identify common entry types. Reusing those details can avoid redundant calls, especially on network filesystems, container mounts, external drives, and large directories.
Basic example
from pathlib import Path
path = Path("data/report.csv")
if path.info.exists():
if path.info.is_file():
print("regular file")
elif path.info.is_dir():
print("directory")
The example checks existence and type through info. Reading and writing still use normal Path methods. Metadata inspection does not open the file and does not prove that a later operation will succeed.
Directory iteration
from pathlib import Path
root = Path("project")
for entry in root.iterdir():
if entry.info.is_dir():
print("Directory:", entry.name)
elif entry.info.is_file():
print("File:", entry.name)
elif entry.info.is_symlink():
print("Symlink:", entry.name)
This is the natural use case. When a program examines thousands of entries, avoiding repeated metadata calls can matter. The gain depends on the operating system, filesystem, cache state, and how the paths were created, so measure before making performance claims.
Cached information and staleness
Information associated with a path can be cached. A cached answer may remain available even after another process changes the filesystem. A file might be deleted, replaced, or converted into a directory while your object still reflects the earlier state.
Treat cached metadata as a useful snapshot, not a permanent guarantee. When a current answer is essential, obtain a fresh path object or use the appropriate operation for your Python version.
from pathlib import Path
original = Path("input.txt")
print(original.info.exists())
# Later, after possible external changes
fresh = Path(original)
print(fresh.info.exists())
This matters in upload processors, file watchers, queues, and concurrent services. The state may change between a check and its use. That race is commonly called TOCTOU: time of check to time of use.
Checks are not permissions
A path being a file does not mean your process can read it. Permissions may change, the file may disappear, or the parent directory may become inaccessible. Always handle the real operation.
from pathlib import Path
config = Path("config.toml")
if config.info.is_file():
try:
text = config.read_text(encoding="utf-8")
except OSError as error:
print("Read failed:", error)
Robust programs use preliminary checks for routing and user feedback, then treat the actual open, read, write, rename, or delete as the final authority.
Symbolic links
Links require an explicit policy. There are two different questions: is the path itself a symlink, and what type is its target? Some operations follow links while others inspect the link. Verify the behavior in the documentation for the exact Python version you support.
Backup and synchronization tools should decide whether to ignore links, preserve them, or follow only targets inside an approved root. Following a link blindly can escape the expected directory tree.
Building a simple inventory
from pathlib import Path
def inventory(root: Path) -> dict[str, int]:
totals = {
"files": 0,
"directories": 0,
"links": 0,
"other": 0,
}
for entry in root.iterdir():
if entry.info.is_symlink():
totals["links"] += 1
elif entry.info.is_file():
totals["files"] += 1
elif entry.info.is_dir():
totals["directories"] += 1
else:
totals["other"] += 1
return totals
The function classifies one level. For recursive scans, use a stack or queue and define how to handle inaccessible directories, links, cancellation, and very large folders.
Iterative recursive scanning
from pathlib import Path
def walk_files(root: Path):
pending = [root]
while pending:
current = pending.pop()
try:
entries = current.iterdir()
except OSError:
continue
for entry in entries:
if entry.info.is_symlink():
continue
if entry.info.is_dir():
pending.append(entry)
elif entry.info.is_file():
yield entry
This design avoids Python recursion depth limits and does not materialize an entire directory listing. Production code should log failures, support cancellation, and impose limits when the tree is not trusted.
Performance measurement
Do not assume that cached metadata always produces a large improvement. Kernel caches, directory formats, storage latency, and Python implementation details all affect results. Benchmark with representative data.
from pathlib import Path
from time import perf_counter
root = Path("dataset")
start = perf_counter()
count = sum(1 for p in root.iterdir() if p.info.is_file())
elapsed = perf_counter() - start
print(count, elapsed)
Run several rounds, account for warm caches, and compare equivalent implementations. A directory with ten files cannot represent a production tree containing millions.
Version compatibility
Path.info is a recent addition. Libraries supporting older Python releases need a fallback.
from pathlib import Path
def is_regular_file(path: Path) -> bool:
info = getattr(path, "info", None)
if info is not None:
return info.is_file()
return path.is_file()
Centralize compatibility rather than scattering version checks. Declare the minimum Python release in pyproject.toml and test all supported versions in CI.
Combining info with matching
Classification works well with glob, rglob, suffix checks, and custom filters. Read the Academify guides to Python pathlib, glob patterns, the os module, and exception handling.
from pathlib import Path
for entry in Path("logs").glob("*.log"):
if entry.info.is_file():
print(entry)
A matching name does not guarantee a regular file. A directory, symlink, socket, or other entry can use the same suffix.
Special filesystem entries
Unix systems may expose sockets, FIFOs, block devices, and character devices as paths. If your application expects only normal files, reject anything else explicitly. Opening a FIFO may block, and interacting with a device can have serious effects.
File-processing services should use allowlists: accept regular files and known directories, then reject unknown types by default.
User-controlled paths
Path.info does not prevent path traversal. For names received through a web form or API, resolve the candidate against an approved root and verify containment.
from pathlib import Path
ROOT = Path("uploads").resolve()
def safe_path(name: str) -> Path:
candidate = (ROOT / name).resolve()
if candidate != ROOT and ROOT not in candidate.parents:
raise ValueError("Path escapes approved root")
return candidate
After validation, still handle failures during the real operation. Consult the official pathlib documentation and os documentation for platform details.
Testing code that uses Path.info
Create temporary directories with files, subdirectories, broken links, and permission edge cases. Verify classification and fallback behavior. Avoid tests that depend on the developer machine.
from pathlib import Path
def regular_names(root: Path) -> list[str]:
return sorted(
entry.name
for entry in root.iterdir()
if entry.info.is_file()
)
Tests should also simulate deletion between classification and reading. The correct result is usually a handled exception, not an assumption that the earlier check remains true.
When to use it
Use Path.info when classifying many entries, especially those produced by directory iteration. It fits inventories, batch processors, build systems, static-site generators, file browsers, and backup planning.
For one isolated check, Path.is_file() or Path.is_dir() may remain simpler. Choose based on readability, compatibility, and measured workload.
Common mistakes
Common mistakes include trusting cached data forever, ignoring TOCTOU races, following links without a policy, failing to catch OSError, assuming availability on old Python versions, and treating metadata as a security boundary.
Separate concerns: validate the approved root, classify the entry, perform the operation, and handle failure. Small functions make these decisions testable.
Conclusion
pathlib.Path.info makes filesystem classification expressive and can reuse metadata gathered during directory iteration. That can reduce redundant system calls in large scans. The cache also introduces responsibility: filesystems change, permissions differ, and links may lead outside expected locations. Combine the feature with exception handling, path validation, explicit symlink rules, compatibility fallbacks, and realistic benchmarks. This approach delivers performance without sacrificing correctness or safety.







