Folder Version Incrementer
Folder Version Incrementer
- trigger
- trigger_image
- trigger_video
- version_string
- version_number
- folder_name
- subfolder_path
- filename_prefix
- output_filename
- source_stem
- current_version_token
- next_version_token
- next_version_stem
Folder Version Incrementer exists because the author got annoyed with folder methods. Likhith-24 (who publishes this pack as Code2Collapse on GitHub, and posts on r/comfyui) said as much in his launch post: he had "annoying feelings about folder methods," so he built this node. The problem it solves is the one every ComfyUI user hits after their tenth save: output.png, output (1).png, output (2).png - no order, no grouping, no way to know which pass is the latest.
This node scans your output directory and hands you the next free version number as real folder structure: output/<shotname>/<MM-DD-YYYY>/v001/<shotname>.png, then v002, v003… Each day starts fresh at v001, so a week of sessions doesn't produce a single flat folder of 300 files. It's one of the three FolderIncrementer nodes in ComfyUI-CustomNodePacks, and it's the workhorse of the trio.
How it works
The design philosophy is in the details:
- Filesystem-based, not counter-file-based. It scans the actual directory for
v001,v002, … and returns the next one that doesn't exist. No JSON counter that drifts out of sync when you delete files or move folders - the truth lives on disk. - Cancel-safe. The version folder is claimed when the node actually runs. If you cancel a queue mid-way and that node never executes, no version number is wasted.
- It derives its folder name from your source file. Connect
trigger_image/trigger_video(or asource_path/source_filename), andSC_30_SHT50.mp4becomesoutput/SC_30_SHT50/<date>/v001/SC_30_SHT50.mp4. The pack's JS companion auto-fills the source name from whatever loader you connect. - Optional suffix for pass tagging. Want to tag a pass without cluttering the folder?
suffixwithsuffix_mode=filenameappends to the basename (clip_mask.mov);subfoldernestsv001/mask/;foldercreates a separate top-level folder with its own versioning. No more downstream Concatenate nodes just to tag a run.
The outputs that matter
The node spits out a lot of strings - here's what you actually wire:
version_string(v001) andversion_number(1) - the version itself.subfolder_path(shot/v001) - wire this into Save Image'ssubfolderinput, or fold it into a filename prefix, and your saves land in the right place automatically.filename_prefixandoutput_filename- ready-to-use paths for Save Image / VHS-style save nodes.folder_name- the sanitized shot name, if you need it separately.
Wire version_string into your Save Image filename_prefix and every queued prompt produces a clean ordered file series. That's the whole loop.
Installing it
Ships in ComfyUI-CustomNodePacks. ComfyUI Manager → search "CustomNodePacks", or:
cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git
Needs nothing beyond stdlib file operations, so it works the moment the pack loads. The pack overall wants opencv-python>=4.7.0 and scipy>=1.10.0 for other nodes - add just those if missing (skip the full requirements.txt; it can clobber ComfyUI's torch). Restart ComfyUI.
Common issues
- Versions aren't incrementing - check
date_format. Versions are scoped per day; if you changed the format string, the date folder changes and scanning restarts at v001. - The folder name is "default" - nothing is connected upstream, so the node fell back to the
labelwidget. Connect a loader or setsource_choice/custom_name. - Output landed somewhere unexpected -
base_pathoverrides the output root; leave it empty for ComfyUI's normal output dir. - You want to control the version, not just advance it - that's the job of the pack's Folder Version Set (reserve slots) and Folder Version Check (report the current state).
The honest take: it's the rare utility node that changes your habit. Once your saves are versioned folders instead of (1), (2), (3), you'll wonder how you ever QA'd a sweep without it.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| prefix | STRING | v | Prefix before the version number (e.g. 'v' → v001) |
| padding | INT | 31–10 | Zero-pad width (3 → 001) |
| suffix | STRING | Optional tag like '_mask' or '_wan'. WHERE it lands is controlled by suffix_mode: filename → '.../v001/clip_mask.mov' subfolder → '.../v001/mask/clip.mov' (separate folder per run) folder → 'ATG_..._mask/<date>/v001/clip.mov' (separate top folder) Leave empty to disable. Sanitized for cross-platform safety. | |
| suffix_mode | COMBO | filename | Where the `suffix` is applied: filename — append to the output basename (legacy behaviour) subfolder — nest a folder AFTER the version, e.g. v001/mask/ — keeps mask vs wan outputs of the SAME run side by side, same version folder — append to the TOP folder name, e.g. ATG_..._mask/ — fully separate folder tree with its own versioning. For subfolder/folder a leading '_' or '-' is stripped from the folder name (so '_mask' → 'mask') and the basename is left clean. |
| label | STRING | default | Fallback folder name (used only when no source file is connected) |
| date_format | COMBO | MM-DD-YYYY | Date format for the date subfolder (e.g. 02-22-2026 or 2026-02-22) |
| path_style | COMBO | auto | Path separator style for output strings. auto=detect from current OS, windows=backslash, linux/macos=forward slash. Use 'auto' unless you design workflows on one OS and run on another. |
| source_choice | COMBO | auto | Where the source name comes from. 'image' → trigger_image, 'video' → trigger_video, 'auto' → prefer video if connected, else image, else legacy `trigger`. 'exr' → prefer an EXR/DPX/CIN plate (sequence or single); works WITHOUT a trigger — wire the plate path STRING into `source_path` and the stem is derived from it. 'custom' → use the ``custom_name`` widget verbatim and ignore all triggers. |
| name_format | COMBO | basename | How to format the detected filename for folder + prefix: basename — strip extension only (e.g. clip_2160_25fps) strip_tags — also strip trailing res/fps tags (clip) first_segment — keep only the first chunk before . or _ (clip) The original file extension is preserved on output_filename. |
| triggeropt | * | Legacy generic trigger – connect any output here. | |
| trigger_imageopt | IMAGE | Connect a LoadImage / image source here. Used when source_choice = 'image' or 'auto'. | |
| trigger_videoopt | * | Connect a LoadVideo / VHS_LoadVideo / video source here. Used when source_choice = 'video' or 'auto' (preferred). | |
| source_filenameopt | STRING | Auto-filled from the connected loader (basename only, no extension). Drives folder name + output basename. Extension is stored separately in source_extension for output_filename. May also be a FULL PATH — the basename is extracted automatically. | |
| source_extensionopt | STRING | Auto-filled file extension from the connected loader (e.g. .mp4, .mov). Used only for output_filename — not part of the folder name. | |
| source_pathopt | STRING | Full path to a source media file (image / video / EXR / DPX sequence). When provided, the node extracts the filename stem from this path and uses it as the source name — this takes PRECEDENCE over source_filename and custom_name. Connect a STRING output here (e.g. an OCIORead 'source' widget, or any loader that exposes its file path as STRING). The extracted stem is returned on the `source_stem` output, and a trailing version token (e.g. _v001) is incremented to _v002 on the `next_version_token` / `next_version_stem` outputs. | |
| custom_nameopt | STRING | Manual source name. Only used when source_choice='custom'. May include an extension (e.g. 'my_shot.mp4'); if no extension is given, output_filename will have none either. Sanitized for cross-platform safety. | |
| base_pathopt | STRING | Override base output directory. Leave empty → ComfyUI output dir. | |
| folder_name_overrideopt | STRING | Force a specific folder name instead of deriving from the input filename. Sanitized for cross-platform safety. | |
| reserve_versionopt | BOOLEAN | false | If True, create the version directory and write a `.reserved` marker file to claim the version number atomically. Prevents collisions in batch/render-farm workflows. Leave False for normal use (the directory will be created by ComfyUI's Save node when output is actually written). |
Outputs (10)
| Name | Type | Description |
|---|---|---|
| version_string | STRING | Zero-padded version string, e.g. `v001`. |
| version_number | INT | Raw integer version number. |
| folder_name | STRING | Sanitized folder name derived from the input source (or label). |
| subfolder_path | STRING | Full subfolder path: `<base>/<folder>/<date>/<version>`. |
| filename_prefix | STRING | Filename prefix combining folder + version (for SaveImage). |
| output_filename | STRING | Final output filename including extension. |
| source_stem | STRING | Filename stem extracted from the connected source (extension and frame token stripped). e.g. `B_0151C002_260527_134258_a1IE7_v001`. |
| current_version_token | STRING | Version token found at the end of the source stem, e.g. `v001`. Empty when the source name has no trailing version token. |
| next_version_token | STRING | Source version token incremented by one, e.g. `v002`. Empty when the source name has no trailing version token. |
| next_version_stem | STRING | Source stem with its version token incremented, e.g. `B_0151C002_260527_134258_a1IE7_v002`. Empty when the source name has no trailing version token. |