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