File
Overview
Section titled “Overview”The File trigger watches a folder, the pool. Every file that arrives there and matches the filter starts a run. Typical sources are an ERP that saves documents as PDF, a scanner or RUNOS’s PDF printer.
Before the run starts, the trigger reads the file’s text. If it contains script blocks (#RUNOS … #RUNOS), RUNOS takes values for this run from them, for example the invoice number and recipient from the ERP printout.
Per file:
- On every check (
CronExpression) the trigger lists the matching files in the pool. - It waits briefly until a file is completely written and not empty. If it is still empty or locked after about two seconds, it is picked up on the next check.
- The file is moved into its own job folder:
<Pool>\Spooler\<ID>\<file name>. It now belongs to this run, and no file is processed twice. - If
NewNameis set, it is renamed. - With
GetFileContent, RUNOS reads the text and evaluates the script blocks. - The run starts.
| Result of the run | What happens to the file |
|---|---|
succeeded, DeleteAfter: false |
stays in its job folder in the spooler (archive) |
succeeded, DeleteAfter: true |
is deleted, together with its job folder |
| failed | is moved to <Pool>\Spooler\Failed\<ID>\. Once the cause is fixed, put it back into the pool. |
If an action has already moved the file elsewhere, it stays there. Several running workflows can watch the same pool; which workflow gets a file is then decided by its script blocks, see Shared pool. Two workflows with the same name cannot share a pool: the second one doesn’t start, and RUNOS names the workflow that holds the folder.
Structure
Section titled “Structure”"Trigger": { "Type": "File", "Name": "Inbox", "Parameters": { "Pool": "C:\\RUNOS\\Invoices", "Filter": "*.pdf", "CronExpression": "0/15 * * * * ?", "ProcessMode": "Single", "ConcurrentJobs": 5, "DeleteAfter": false, "GetFileContent": true }}| Parameter | Default | Meaning |
|---|---|---|
Pool |
– | The watched folder. Created if missing. Placeholders such as %userdocuments% are allowed. |
Filter |
*.* |
File pattern, e.g. *.pdf or INV_*.txt |
CronExpression |
0/15 * * * * ? |
How often the folder is checked, see cron expressions. Default: every 15 seconds. When the PDF printer saves a file into the pool, the trigger also checks right away. |
ProcessMode |
Single |
Single: one run per file. Multi: one run for all files of a check. |
ConcurrentJobs |
5 |
In Single mode: how many files are processed at the same time |
DeleteAfter |
false |
true: after a successful run the file’s job folder is deleted, with everything actions put there (e.g. the parts of the PDFEditor’s Split). Applies to the whole run, not to a single action. |
NewName |
– | New file name in the spooler, e.g. Invoice_%yyyy%-%MM%-%dd%. Without an extension the old one is kept. |
RepeatCount |
0 |
The trigger stops after this many checks (by CronExpression). 0 = unlimited. |
GetFileContent |
true |
Read the file’s text and provide it as {{FileContent}}. Needed for script blocks. |
RemoveScriptFromFile |
false |
Remove script blocks from the file after reading, for TXT, JSON, XML and PDF. In a PDF the block’s text is deleted, not covered: it can be neither seen nor copied, and the rest of the page stays where it was, including text under or next to the script (e.g. small script text printed over an invoice line). If the ERP prints characters between the blocks, e.g. ` |
ScriptStart, ScriptEnd |
from the settings | Own markers for this trigger’s script blocks |
Single is almost always right: every file has its own run with its own data. With Multi, {{Trigger.Response.Results}} contains all files of a check, and {{FilePath}} points to the last one read.
Text that is read
Section titled “Text that is read”| File type | How |
|---|---|
.txt, .json, .xml |
as text |
.pdf |
the text of all pages is extracted. Scanned PDFs without a text layer give no text. |
| others | no text; the workflow still runs, without FileContent and script blocks |
Available values
Section titled “Available values”| Placeholder | Content |
|---|---|
{{FilePath}} |
full path of the file in the spooler |
{{FileName}} |
file name (after NewName) |
{{FileContent}} |
text read, for PDF the extracted text |
{{Trigger.Response.Results}} |
report per file, see below |
{{Trigger.Meta.SpoolerFolder}} |
path of the spooler folder |
{ "FilePath": "C:\\RUNOS\\Invoices\\Spooler\\3f2a…\\INV-2026-0001.pdf", "FileName": "INV-2026-0001.pdf", "OriginalName": "INV-2026-0001.pdf", "FileSize": 48211, "Content": { "Loaded": true, "Chars": 1834, "Preview": "Invoice no. …" }, "Scripts": { "Found": 1, "Parsed": 1, "Ignored": 0, "Invalid": 0 }}With RemoveScriptFromFile, Scripts also holds RemovedFromFile (true when the blocks were removed) and, for PDFs, RemovedBlocks (number of blocks removed).
Script blocks
Section titled “Script blocks”A script block is a short text in the file that changes this one run: it sets values in InitialData, changes parameters of actions or adds actions. The saved workflow JSON stays unchanged. This lets an ERP that can only print or write text files tell RUNOS who an invoice goes to and which data belongs in the XRechnung.
#RUNOS InitialData.Invoice.BT1=INV-2026-0001 #RUNOS#RUNOS SendMail.To=accounting@customer.com #RUNOSA block sits between a start and an end marker, both #RUNOS by default (changeable under Settings → Script blocks or with ScriptStart / ScriptEnd). If the content starts with { and ends with }, it is JSON; if it starts with path=, it is the shorthand; anything else is ignored.
Shorthand
Section titled “Shorthand”Each block contains exactly one statement path=value. The first part of the path decides the target:
| Path starts with | Target | Example |
|---|---|---|
InitialData. |
a value in this run’s InitialData |
InitialData.Invoice.BT1=4711 |
| name of an action | a parameter of that action (.Parameters may be omitted) |
SendMail.To=a@b.com |
newAction. |
a new action, see below | newAction.Notify=SMTP |
| anything else | a global value, readable as {{Name}} |
Customer=ACME → {{Customer}} |
- The value runs from the first
=to the end marker, across several lines too (e.g. a mail text). - Values are text (
Qty=5→"5"). Values written as JSON are read as JSON:Tags=["a","b"]is a list. "…"keeps leading and trailing spaces. Text between the text markers (default***) is taken exactly as written.{{…}}placeholders stay text and are resolved later when the action runs.
JSON form
Section titled “JSON form”#RUNOS {"InitialData":{"Invoice":{"BT1":"INV-2026-0001","BT2":"2026-10-08"}}} #RUNOS| Key | Effect |
|---|---|
InitialData |
laid over the run’s InitialData |
Actions |
parameters for actions, {"SendMail":{"To":"a@b.com"}}, or action blocks {"Name":…, "Type":…, "Parameters":{…}} |
| anything else | global values |
If a program writes a long JSON block into a PDF and breaks the line in the middle of a value, RUNOS joins the value again.
Merging, lists and rows
Section titled “Merging, lists and rows”- An existing key gets the new value, a new key is added, everything else stays. Objects are merged key by key, lists are replaced completely.
- Several blocks are applied in their order; the later one wins.
- A number segment in the path is a row of a list, counted from 1:
InitialData.Items.2.Article=Nut. No number may be skipped. - For the repeating groups of XRechnung (BG-25 lines, BG-23, BG-17 …) it works without numbers: a field the current row already has starts the next one. See the XRechnung example.
New actions
Section titled “New actions”#RUNOS newAction.Notice=SMTP #RUNOS#RUNOS Notice.To=boss@example.com #RUNOS#RUNOS Notice.Subject=New file {{FileName}} #RUNOSScript from the editor
Section titled “Script from the editor”The workflow editor shows which blocks a file needs for a particular workflow under Script (next to Visual / JSON):
- On the left, tick what the file should supply: values from
InitialDataand parameters of the actions, including the actions insideIf,LoopandParallel. Ticking a group (e.g.InitialDataor an action) ticks everything below it. Lists such as invoice lines are chosen as a whole, because a block always replaces a list completely. When the view is first opened,InitialDatais ticked. - On the right is the finished script with the workflow’s current values as examples, in shorthand (one block per value, lists row by row) or as one JSON block. The markers are this trigger’s or those from Settings.
- Copy puts it on the clipboard. In the ERP or the template that produces the file, replace the example values with the real ones.
The script is built from the JSON in the editor, saved or not, and cannot be edited there. Switched-off actions, actions without a name and OnError actions are left out, because the trigger does not find them. RUNOS remembers the selection and the format per workflow. If the workflow has no File trigger, the view says so. In shorthand every value is text (5 arrives as "5"); where the type matters, choose JSON.
Shared pool
Section titled “Shared pool”If only one running workflow watches the pool, write the blocks as above, without a workflow name.
If several running workflows watch the same pool, every block starts with the name of the workflow it is for: Workflow.Action.Parameter=value. Each file is taken from the pool only once and its blocks are read. Only the workflows the file names run, each with its own copy in its own job folder and only with its own blocks (without the name in front). Workflows the file does not name do not start.
#RUNOS Invoice.InitialData.Nr=4711 #RUNOS#RUNOS Invoice.SendMail.To=customer@example.com #RUNOS#RUNOS Archive.InitialData.Folder=2026 #RUNOSHere Invoice and Archive run, a third workflow on the same pool does not. In the JSON form the workflow name is the outer key:
#RUNOS { "Invoice": { "InitialData": { "Nr": "4711" } }, "Archive": { "InitialData": { "Folder": "2026" } } } #RUNOS- Case does not matter. Leave out spaces and any characters other than letters, digits,
_and-: the workflowSend invoiceisSendinvoicein a block. The shorthand needs a name that starts with a letter; otherwise use the JSON form. - If a file names none of the pool’s running workflows (including blocks without a workflow name), it is rejected and goes to the
Failedfolder, with a message saying which workflows share the pool. - A name no running workflow of the pool has (e.g. a typo or a stopped workflow) is ignored; the log reports it as
ScriptForUnknownWorkflow. - Each workflow handles its copy with its own settings (
NewName,DeleteAfter,RemoveScriptFromFile,ProcessMode…). Which workflows got a file is in the log underFileShared. - Whether a pool is shared is decided when the file arrives: if workflows are stopped and only one is left, the form without names applies again.
Faulty blocks
Section titled “Faulty blocks”A block that cannot be read (invalid JSON, path=value not recognizable, missing row number, unknown action type …) rejects the file: it goes to the Failed folder, and you get a message with the block number and the reason. The same applies to a file that clearly contains script data but no markers. What RUNOS read is in the log under ScriptShorthandParsed or ScriptJsonParsed.
Form in the editor
Section titled “Form in the editor”In the diagram of the workflow editor the trigger has a form:
- Folder: Watched folder (
Pool) and File filter (Filter). - Checking: Check the folder (
CronExpression) and Stop after (RepeatCount). - Processing: Runs – one run per file or for all files of a check (
ProcessMode); Files at the same time (ConcurrentJobs, only with one run per file); Rename the file to (NewName); Delete the file after a successful run (DeleteAfter). - Content and script blocks: Read the file’s text (
GetFileContent), Remove script blocks from the file (RemoveScriptFromFile), Block start marker and Block end marker (ScriptStart,ScriptEnd).
The schedule is picked instead of typed: Every … seconds, Every … minutes, Every hour (at minute …), Every day, Monday to Friday, On chosen weekdays (click the days) or Once a month (day 1–31 or the last day), each with a time. The cron expression it makes is shown below. For anything else choose Custom (cron expression) and type the expression; an expression the picker cannot show (e.g. 0 0 8-17 ? * MON-FRI) opens that way by itself. Parameters the form does not know are listed under Other parameters.
Example
Section titled “Example”Every PDF that lands in C:\RUNOS\Inbox is deleted after a successful run. The program that creates the PDFs writes the recipient into it as a script block:
#RUNOS Send.To=customer@example.com #RUNOS{ "Name": "Mail inbox", "Autostart": true, "Trigger": { "Type": "File", "Name": "Inbox", "Parameters": { "Pool": "C:\\RUNOS\\Inbox", "Filter": "*.pdf", "CronExpression": "0/10 * * * * ?", "NewName": "Document_%yyyy%-%MM%-%dd%_%HH%%mm%%ss%", "DeleteAfter": true } }, "Actions": [ { "Type": "MAPI", "Name": "Send", "Parameters": { "Client": "Outlook", "Mode": "Display", "To": "", "Subject": "Your document {{FileName}}", "Attachments": "{{FilePath}}" } } ]}