Load Text Files from ZIP
Batch-prompt from captions locked inside a zip
- zip
- texts
- names
- text
- name
- count
- skipped
Load Text Files from ZIP reads every text file inside a zip archive and hands you two views of them at once: the whole pile as lists, and a per-file stream that runs everything downstream once per file. That second part is the killer feature. You know how training data ships as folders of images with a same-named .txt caption beside each one? This is how you feed that exact arrangement to a sampler without unpacking anything - one file becomes one generation, caption and all.
It's a WAS Node Suite node (find it under WAS Suite/Archive), part of the pack's files-and-archives family that treats a zip as something to read on the wire instead of a thing you excavate first.
How it works
Point the file menu at an archive (it lists every .zip in ComfyUI's input, output, and temp folders, tagged with where it lives) and set pattern. * takes every text file at any depth; *.txt takes every .txt in any folder; cat_*.txt takes only those named that way. A / anchors the pattern at the archive root, so captions/**/*.txt reads one folder and everything under it. Case is ignored. Like its image sibling, it can take a ZIP socket from Open ZIP, which overrides the menu and opens the archive once however many nodes read it.
Each file comes out in two shapes because the two shapes serve two different graphs:
- texts (an ARRAY) - every file's text on one wire, index-aligned with names. Grab one with Text List Get when you want to fetch a specific caption.
- text (a STRING list) - the same texts, but wired into something like a sampler's prompt, ComfyUI runs the whole graph once per entry. That's the batch loop. Its partner name carries the matching filename each run, so you can feed it into Image Save's filename prefix and every render comes out named after the caption that made it.
That "runs downstream once per file" behaviour is the thing most people don't expect from a loader, and it's what makes caption-driven batch prompting possible without a single loop node.
The other outputs
count tells you how many files were read, and skipped how many entries didn't make it - wrong kind of file, an unsafe name, a symlink, encrypted, damaged, or not UTF-8 text. Every rejection is named in the log, so a silent gap is easy to trace. If the archive is missing, isn't readable, or holds nothing your pattern picks, the prompt stops and says which.
Installing it
Same routine as every WAS node: ComfyUI Manager → "WAS Node Suite v3", or
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git
restart, done. Requires ComfyUI 0.14.0+ and Python 3.10+, and the pack installs no dependencies of its own.
Where people get burned
The pattern is the trap. * matches at any depth, so it quietly grabs every .txt (and .json, and anything text-shaped) the archive holds - if your zip mixes captions with readme files, be specific. And remember the text output is a list wire: if you wire it into a node that doesn't iterate lists, you'll only see the first (or last) file's contents. If you want one caption per run instead of the whole archive, use texts/names with a picker rather than the list output. Oh, and files a zip was encrypted with won't read - that's a "skipped" entry, not a hang.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| file | COMBO | Which archive to read. The menu lists every .zip in ComfyUI's input, output and temp folders and in any folder added under paths.allow_read, each tagged with where it sits. Ignored while the zip socket is connected. | |
| pattern | STRING | * | Which entries inside the archive to read. '*' takes every text file at any depth, '*.txt' every .txt in any folder, and 'cat_*.txt' only those named that way. |
| zipopt | ZIP | The archive to read, from Open ZIP. Connected, it is used and the menu is ignored, so the archive is opened and indexed once however many nodes read it. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| texts | ARRAY | Every file's text on one wire, in the order the names sort, for Text List Get, Text List Slice and Text List Length. Entry 3 here is the text of name 3 in the 'names' output. |
| names | ARRAY | The name each text came from, on one wire and in the same order, such as 'captions/cat.txt'. The folders inside the archive are kept, so two files called cat.txt in different folders stay apart. |
| text | STRING | The same texts as a STRING list, so the graph below runs once per file: wire it into a sampler's prompt to render every caption in the archive. |
| name | STRING | The file name that goes with each run of the 'text' output, so a saved image can carry the name of the caption that made it. Wire it into Image Save's filename_prefix beside the matching text. |
| count | INT | How many files were read, which is the length of both lists. |
| skipped | INT | How many entries the archive holds that were not read: a kind this node does not read, one unsafe to unpack, one damaged. The log names every one. |