CLI AI

Merge and split PDFs from the command line

2026-08-13

pdfunite a.pdf b.pdf out.pdf joins documents and pdfseparate in.pdf page-%d.pdf breaks one apart. Both come from poppler-utils and are fast and lossless. What they can't do — extract a page range as a single document, or compress — is ghostscript's job, and that split of labour is the whole article.

1. How many pages is this

clai
$ clai how many pages does merged.pdf have→ pdfinfo merged.pdf | grep '^Pages'Pages:           4

pdfinfo prints a couple of dozen metadata lines and you usually want one of them. It doubles as the sanity check after every operation below.

2. Join several files

clai
$ clai merge invoice.pdf and contract.pdf into one document→ pdfunite invoice.pdf contract.pdf merged.pdf

The last argument is always the result, everything before it is a source, in the order they'll appear. The command prints nothing — check with pdfinfo.

3. Break it into single pages

clai
$ clai split merged.pdf into one file per page→ pdfseparate merged.pdf page-%d.pdfpage-1.pdfpage-2.pdfpage-3.pdfpage-4.pdf

The %d is required — the page number goes there. The listing above comes from ls -1; pdfseparate itself is silent.

4. Extract a page range

clai
$ clai pull out pages 2 through 3→ pdfseparate -f 2 -l 3 merged.pdf slice-%d.pdfslice-2.pdfslice-3.pdf

-f is the first page, -l the last. Note what you got: two files, not one two-page document — and the numbering keeps the original page numbers.

5. A range as one document

clai
$ clai extract pages 2 to 3 into a single document→ gs -q -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dFirstPage=2 -dLastPage=3 -sOutputFile=pages-2-3.pdf merged.pdf

poppler has no command for this, so ghostscript takes over. Verified: pdfinfo pages-2-3.pdf reports Pages: 2. Without gs the route is pdfseparate followed by pdfunite slice-2.pdf slice-3.pdf range.pdf, which gives the same two pages.

6. Make the file smaller

clai
$ clai compress the pdf so it fits in an email attachment→ gs -q -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dNOPAUSE -dBATCH -sOutputFile=small.pdf merged.pdf

Verified on the demo file: 84991 bytes before, 31876 after — nearly a third of the size. /ebook is the middle profile; /screen squeezes harder and shows it on images, /prepress protects quality. Text is untouched either way; what shrinks is the raster images inside.

Gotchas

  • pdfunite overwrites its last argument. That slot is always the output. pdfunite part1.pdf part2.pdf with no third name destroys part2.pdf — there is no "last file is a source" convention here.
  • pdfseparate never joins. Even with -f and -l you get a pile of one-page files. Putting them back together is pdfunite's job, or ghostscript's.
  • Neither tool opens an encrypted PDF. Remove the password first (qpdf --decrypt where it's available); otherwise both simply refuse to read the file.

Related questions

How do I rotate pages? Ghostscript can re-emit a file with -dAutoRotatePages=/None, but rotating one specific page is far simpler in qpdf.

How do I get the text out? pdftotext file.pdf - prints the text to the terminal. For scans with no text layer you need OCR instead.

How do I turn pages into images? pdftoppm -png -r 150 file.pdf page writes page-1.png, page-2.png and so on at 150 dpi.

See also

CliAI knows which of the two toolchains does the job you described, and shows the command before it runs. Install it in one line.