os.path.lexists
The 'does the link exist' question isfile gets wrong
- path_in
- lexists
Here's the edge case that makes people think their isfile check is broken: a symlink pointing at a file that's been moved. The link itself exists, the target doesn't. isfile says False because it follows the link to nothing. But something is there - and if you're trying to clean up stale links or detect "the entry exists even if it dangles," you want the node that doesn't follow links at all.
os.path.lexists is that node, from the ovum/path/os.path family in comfy-ovum. It mirrors Python's os.path.lexists(), which is the "l" variant of exists: it checks the directory entry itself, not the target it points at.
How it works
Predicate, returns a BOOLEAN (lexists). Path from:
- path (STRING, required): the widget.
- path_in (PATHLIKE,STRING, optional): link-only; overrides the widget when connected.
The semantics: True if the entry exists - a regular file, a directory, or a symlink, even a symlink whose target is gone. False only if nothing is there at all. It never raises on missing paths. One BOOLEAN out.
The difference that matters
The stdlib's os.path.exists and its wrapper behave like isfile/isdir in this respect - they follow symlinks, so a broken link reports as non-existent. lexists is the odd one out: it reports on the link itself. Concretely, for a dangling symlink:
os.path.exists→Falseos.path.isfile→Falseos.path.lexists→True← the only one that says "a directory entry is here"
Where you'd use it
- Cleanup graphs. Before you delete "dead" entries in a model or output folder, use
lexists+islinktogether:lexists == Trueandislink == Trueandisfile == Falseis the precise broken-symlink signature. Delete those and you've tidied the folder without touching real files. - Non-destructive existence checks. If you're building a graph that moves or processes entries and you want "is there something here" without caring about target state,
lexistsis the looser, safer predicate. - Model directory forensics. Broken links in
models/are a classic cause of "loader shows the model, load fails."lexistsis the tool that proves the entry is a stale link.
Installing it
Standard pack install, once:
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
Or ComfyUI Manager → "comfy-ovum" → Install → restart. No models, no extra deps.
Gotchas
- For 99% of workflows - "is my output file there?" - you want
isfileorexists, notlexists. Lexists answers a different question, and using it where you meanisfilewill make you think files exist when they're just dangling links. - On Windows, junction points and symlinks blur again:
lexistsgenerally works for real symlinks but can be inconsistent for junctions depending on Python version. On Linux/macOS it's exact. - If you're doing this on a path that's a plain (non-link) file, all three predicates agree, and
lexistsbehaves identically toexists. The difference only shows up at the links - which is precisely when you need it.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| path | STRING | — | |
| path_inopt | PATHLIKE,STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| lexists | BOOLEAN | — |