pipeline syntax

Chaining operations, named handles, and pipeline substitution

Details

Construct complex workflows using pipelines, handles, and substitution.

1. Chaining (---)

Multiple operations can be chained together using ---. The output of one stage becomes the input for the next stage. If a stage has no explicit inputs, it automatically uses the result from the previous stage.

pdftl in.pdf rotate right --- crop '(a4)' output out.pdf

You can have as many stages as you like. Each --- separator marks the boundary between stages.

2. Named Handles (X=...)

You can assign single capital letter handles (A-Z) to inputs to refer to them later:

pdftl A=logo.pdf B=content.pdf ...

This allows you to reuse a specific file or result multiple times in different stages (e.g., cat A B A). Handles are visible to all subsequent stages in the same pipeline.

3. Pipeline Substitution (JOB ... DONE)

Similar to command substitution in a shell ($(...) in bash), you can process files in a temporary sub-pipeline and use the result as an input — inline, without saving to a file first.

pdftl JOB in.pdf rotate right DONE main.pdf cat output out.pdf

The commands between JOB and DONE run first, and their output is used as an input at that position. You can also assign the result to a named handle:

pdftl S=JOB in.pdf rotate right DONE S main.pdf cat output out.pdf

Sub-pipelines can themselves contain --- separators to chain operations inside the substitution:

pdftl A=JOB in.pdf rotate right --- stamp logo.pdf DONE ...

Sub-pipelines can be nested arbitrarily. Each DONE always closes the innermost open JOB.

4. Per-file Iteration (EACH ... DONE)

EACH ... DONE applies a sub-pipeline to every input file that precedes it, independently, replacing each input with its transformed result. This is similar to map in functional programming, or xargs in the shell.

pdftl a.pdf b.pdf c.pdf EACH rotate right DONE cat output out.pdf

Here, rotate right is applied to each of a.pdf, b.pdf, and c.pdf in turn. The results are then passed to cat for merging.

The sub-pipeline inside EACH ... DONE receives each input file via the implicit pipeline input _, exactly as if it were a stage after ---. This means you can chain multiple operations inside EACH:

pdftl a.pdf b.pdf EACH cat 1-3 --- rotate right DONE cat output out.pdf

This selects pages 1–3 from each file, rotates them, and merges the results.

EACH and filename substitution

Because each iteration runs as an isolated sub-pipeline with one input file, operations that substitute the current filename (such as add_text) work naturally inside EACH:

pdftl *.pdf EACH insert before 1 --- add_text '/{filename}/(position=center)' DONE      cat output combined.pdf

This inserts a blank title page stamped with each file’s own name before merging everything together.

5. Combining JOB and EACH

JOB and EACH can be freely combined. Both use DONE as their terminator; DONE always closes the innermost open block.

EACH inside JOB: the JOB collects the results of all iterations into a single output:

pdftl R=JOB a.pdf b.pdf EACH cat 1 DONE DONE cat R output out.pdf

EACH selects page 1 from each of a.pdf and b.pdf; the enclosing JOB merges them and assigns the 2-page result to R.

JOB inside EACH: each iteration can use its own sub-pipeline as an additional input. Pass _ explicitly to the JOB to refer to the current iteration’s file:

pdftl a.pdf b.pdf EACH R=JOB _ cat 1 DONE cat R _ DONE cat output out.pdf

For each input file, JOB extracts its first page into R, then cat R _ prepends that first page to the full file.

Siblings: EACH and JOB can appear as siblings in the same input list. Each gets its own DONE:

pdftl a.pdf b.pdf EACH cat 1 DONE R=JOB cover.pdf stamp logo.pdf DONE cat R output out.pdf

The two DONE tokens close EACH and JOB respectively. The outer cat receives: the EACH results (one page from each of a and b) followed by R (the stamped cover), and merges all three.

Examples

Shuffle two documents, then crop the resulting pages to A4

pdftl a.pdf b.pdf shuffle --- crop '(a4)' output out.pdf

Crop all pages to A3 in landscape, and preview the effect of cropping odd pages to A4

pdftl in.pdf crop '(A3_l)' --- crop 'odd(A4)' preview output out.pdf

Save a snapshot of a rotated file, then apply a stamp and save the final version

pdftl in.pdf rotate right output rotated_snapshot.pdf --- background watermark.pdf output final.pdf

Use pipeline substitution (JOB…DONE) to rotate one filebefore merging it with another.

pdftl JOB in.pdf cat right DONE main.pdf cat output final.pdf

Rotate and stamp a.pdf, crop b.pdf, then combine selected pages from both

pdftl A=JOB a.pdf rotate right --- stamp logo.pdf DONE B=JOB b.pdf crop '(a4)' DONE cat A1-3 B2-end output combined.pdf

Join a contract with a stamped copy of itself

pdftl contract.pdf JOB contract.pdf stamp logo.pdf DONE output combined.pdf

Chain multiple operations together where the output of one becomes the input of the next

pdftl in.pdf rotate right --- crop '(a4)' output out.pdf

Assign named handles to inputs to reuse them later in the pipeline

pdftl A=logo.pdf B=content.pdf cat A B A output out.pdf

Assign the result of a sub-pipeline to a named handle

pdftl S=JOB in.pdf rotate right DONE S main.pdf cat output out.pdf

Chain multiple operations inside a sub-pipeline

pdftl A=JOB in.pdf rotate right --- stamp logo.pdf DONE cat A output out.pdf

Apply a sub-pipeline to multiple files independently replacing each with its transformed result

pdftl a.pdf b.pdf c.pdf EACH rotate right DONE cat output out.pdf

Chain multiple operations inside an EACH block (e.g., select pages, then rotate)

pdftl a.pdf b.pdf EACH cat 1-3 --- rotate right DONE cat output out.pdf

Use filename substitution inside an EACH block to add a cover page to each file, with its filename, then merge

pdftl a.pdf b.pdf EACH insert before 1 --- add_text '1/{filename}/(position=center)' DONE cat output combined.pdf

Wrap EACH inside a JOB to collect the results of all iterations into a single handle

pdftl R=JOB a.pdf b.pdf EACH cat 1 DONE DONE cat R output out.pdf

Use a JOB inside EACH to process a specific page and prepend it to the current iteration’s file

pdftl a.pdf b.pdf EACH R=JOB _ cat 1 DONE cat R _ DONE cat output out.pdf

Combine EACH and JOB as siblings in the same pipeline

pdftl a.pdf b.pdf EACH cat 1 DONE R=JOB cover.pdf stamp logo.pdf DONE cat R output out.pdf

Source: pdftl.cli.pipeline

Read online: https://pdftl.readthedocs.io/en/latest/general/pipeline.html

Type: HelpTopic