os.path.splitext
The node that separates your filename from its extension
- path_in
- root
- ext
The most common path operation in any ComfyUI workflow is also the one people reinvent by hand the most: "take frame_0072.png, give me the frame_0072 so I can build frame_0072_upscaled.png." os.path.splitext is that operation. It splits a path into (root, ext) - the name and its extension - so you can modify one without mangling the other.
It's from the ovum/path/os.path family in comfy-ovum, a faithful wrapper over Python's os.path.splitext().
How it works
Returns two STRING outputs:
- root: everything up to (but not including) the final extension.
C:\renders\frame_0072.png→C:\renders\frame_0072 - ext: the extension, dot included.
.png
Path from:
- path (STRING, required): the widget.
- path_in (PATHLIKE,STRING, optional): link-only; overrides the widget when connected.
The split is on the last dot in the final path component, so archive.v2.png → root archive.v2, ext .png. Files with no extension return an empty ext and the whole name as root. Pure string work - no disk access, safe on anything.
The workflow it enables
This is the foundation of dynamic output naming:
- Take a loader's file path, split off the ext.
- Run the root through a format/concat node to append a suffix -
Python String Formatfrom the same pack is perfect:{arg0}_hires. - Re-add an extension (maybe a different one -
.png→.jpg). - Feed the result to your saver.
Now the output name is derived from the input name instead of hardcoded, which means a batch graph renames correctly for every file it touches. It also earns its keep for filtering: checking ext == '.mp4' vs .png to route files to the right branch, or detecting whether a filename already has an extension before you go appending one.
Installing it
Pack-wide, 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
- It's
splitext, notsplit. The plainos.path.splitnode separates folder from filename; this one separates extension from name. They're easy to confuse in a search box, and the results are not interchangeable. - Last-dot rule.
my.file.name→ rootmy.file, ext.name. That matches Python and is usually what you want, but if a file genuinely has dots in its name, splitext won't strip "all extensions." - The dot stays with the extension. If you build output names, remember
extalready includes the leading dot -{root}_hires{ext}givesframe_0072_hires.png, while{root}_hires.{ext}would give you a double dot.
If you wire a saver's path into splitext once, rename logic, extension checks, and output-name construction all fall out of it. It's the highest-value-per-input node in the whole path family.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| path | STRING | — | |
| path_inopt | PATHLIKE,STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| root | STRING | — |
| ext | STRING | — |