Unzip

Action arrow.up.bin

action.unzip

Extract a .zip archive to real files on disk, then send those files downstream. The archive path comes from the upstream payload (typically {{filePath}} from an Input or Directory Changed trigger). A zip of 200 files is just a document of 200 pages — Unzip fans out over the contents so each file flows through the rest of your workflow on its own.

Two outlets, one extraction

A single extraction feeds both outlets — wire whichever fits whether you want one result for the whole archive or one result per file. (Same pattern as Extract Text (PDF)’s Document/Page split.)

Contents

Emits once with the whole archive — the destination directory, a files array of every extracted path, and fileCount. Use it for one action about the whole extraction (e.g. “notify me it’s done”).

File

Fans out — runs everything downstream once per extracted file, each run carrying that file’s filePath, fileName, and index. Use it to route each file by type — image → OCR/vision, text → AI, and so on.

Ports

Inlet
Input (file)
Outlets
Contents (any)
File (any, fans out)

Configuration

FieldTypeDefaultDescription
archivePathVariable picker{{filePath}}The .zip to extract. Pick the upstream variable that holds the path (a bare key, a {{key}} template, or a literal path all work); blank falls back to filePath.
destinationText{{directory}}/{{fileName}}Where to extract. Defaults to a sibling folder next to the archive — this keeps the output out of a watched directory so it doesn’t re-trigger the workflow.
overwriteDropdownoverwriteOn a name collision at the destination: Overwrite, Keep both (suffix), or Skip existing.

Output Variables

Merged onto the incoming payload (so upstream keys are preserved). Which keys you get depends on the outlet you wired.

VariableOutletDescription
destinationContentsAbsolute path to the extraction directory.
filesContentsArray of file refs for every extracted file.
fileCountContentsNumber of files extracted.
filePathFileThis file’s absolute path (drops straight into OCR, PDF, AI, Move…).
fileNameFileThis file’s name.
indexFileThis file’s 0-based position in the archive.
successBothtrue on success; false on a graceful failure (see below).

Error handling

Two tiers, by design. Everyday problems fail gracefully so a workflow can branch on them; only genuine safety violations hard-fail.

Graceful — success: false

Returns a normal payload with success: false and an error reason — never throws, so the run continues and a Condition can route the failure.

  • no_archive_path — no archive path was provided or resolved.
  • archive_not_found — the path is valid but no file exists there.
  • not_a_zip — the file isn’t a readable archive (ditto exits non-zero). This is the “input isn’t an archive” case — it fails gracefully and emits a single success:false payload (not the per-file fan-out).
Hard fail — stops the run

Throws and marks the node failed (the red banner) only for real safety violations:

  • protected location — the archive or destination resolves into a denied path (~/Library internals, ~/.ssh, system roots) or uses .. traversal. iCloud Drive and other cloud folders are allowed.
  • zip-slip / symlink — an entry inside the archive tries to escape the extraction directory or is a symlink. The whole extraction is discarded before anything reaches your destination.

Security

Extraction lands in a private temporary folder first. Every entry is checked to stay inside that folder and symlink entries are rejected, so a malicious archive (zip-slip) is caught and discarded before anything reaches your real destination. Archive and destination paths are validated against the same protected-location rules as Move File; iCloud Drive and other cloud folders are allowed.

Example

Describe every image in a zip: extract, then fan out the File outlet to OCR + an AI vision model.