pdfq 0.1.1

Fast, parallel PDF search with a pdfgrep-compatible CLI
Documentation

pdfq

Crates.io docs.rs License: MIT

Fast, parallel PDF search with a command line compatible with pdfgrep.

pdfq is a from-scratch rewrite in Rust. It extracts text page by page with pdf-extract, matches with the regex crate (or fancy-regex for -P), and searches pages on all cores with rayon. Output format, flags, and exit codes follow pdfgrep so it can be used as a drop-in replacement.

Features

  • pdfgrep-compatible flags: -i, -n, -c, -o, -l, -L, -q, -F, -P, -A/-B/-C, -m, -r, -R, --color, --page-range, and more
  • Parallel page and file processing (rayon)
  • Modern regex engines: Rust regex by default, fancy-regex for -P
  • Optional on-disk cache of extracted page text (--cache)
  • GNU-grep-style exit codes: 0 match, 1 no match, 2 error
  • Colored output honoring GREP_COLORS (mt/ms/mc, fn, ln, se)

Build

cargo build --release

The binary is target/release/pdfq.

Usage

pdfq [OPTION]... PATTERN FILE...

Examples:

pdfq -n "error" report.pdf
pdfq -r -i "todo" ./docs
pdfq -c -e foo -e bar a.pdf b.pdf
pdfq -n -C2 --page-range 3-5 "summary" thesis.pdf
pdfq -l -F "exact string" .

Run pdfq --help for the full option list.

Exit codes

Code Meaning
0 at least one match
1 no match
2 error (bad usage, unreadable file, ...)

With -q, a match wins over errors: exit 0 as soon as anything matches. Errors while walking directories recursively (-r) are reported on stderr but do not change the exit code, matching pdfgrep.

Output format

[filename<sep>][pagenum<sep>]text
  • sep is : on match lines and - on context lines
  • -n prints the page number (pdfgrep has no line numbers, PDFs are pages)
  • -Z replaces the filename separator with NUL
  • context groups are separated by --, but only when lines were actually skipped

Differences from pdfgrep

  • Text extraction uses pdf-extract (pure Rust) instead of poppler, so layout reconstruction can differ slightly on complex PDFs
  • . in a pattern does not match newline (Rust regex semantics; POSIX . does). Multi-line anchors: ^ matches only the start of the page text, $ only the end
  • Recursive walk output is sorted by name for reproducible results; pdfgrep prints raw readdir order
  • --help is generated by clap and lists every option, not pdfgrep's short "commonly used" list
  • No --unac accent folding (option is rejected with a clear error)

Testing

Unit and integration tests (includes a regression suite for the encrypted-PDF password check vs --cache):

cargo test

Differential tests against a reference pdfgrep binary (compares stdout, stderr, and exit codes; program name normalized):

cargo build --release
PDFGREP=/path/to/pdfgrep bash tests/difftest.sh

If PDFGREP is not set, the script uses pdfgrep from PATH and exits 2 when it is missing.

License

MIT