pdfgrep позволяет находить слова, фразы и регулярные выражения внутри одного PDF или целой папки документов, сразу показывать имя файла, номер страницы и строку с совпадением, считать найденные места, выводить контекст и передавать результат другим командам. Основные инструменты вызываются из терминала: шаблон задаётся прямо в команде или читается из файла, область поиска ограничивается списком страниц и масками имён, а для повторной обработки больших документов можно включить кэш извлечённого текста.
Рабочее окно здесь фактически совпадает с оболочкой: пользователь вводит команду, получает поток строк и при необходимости уточняет запрос следующими параметрами. Цветом выделяется найденный фрагмент, перед ним могут стоять имя документа и страница, а отсутствие графических панелей компенсируется тем, что один и тот же вызов легко повторить, сохранить в скрипте или соединить с find, xargs, sort и другими утилитами.
Типичный процесс начинается с простого запроса вида pdfgrep "условия договора" contract.pdf. Затем добавляют нечувствительность к регистру, номера страниц, контекст или рекурсивный обход каталога. Такой порядок удобнее попытки сразу составить длинную конструкцию: на каждом шаге видно, извлекается ли текст из документа, правильно ли оболочка передала кавычки и не слишком ли широк шаблон.
Скачать pdfgrep
- Редактирование PDF
- Русский интерфейс
- Просто новичкам
- Нет графического интерфейса
- Не распознаёт сканы
- Ищет только в PDF
Как устроен поиск в pdfgrep
Каждая страница PDF перед проверкой превращается в последовательность текстовых строк средствами библиотеки Poppler. Шаблон сопоставляется не с бинарным содержимым файла и не с внешним индексом, а с извлечённым текстовым слоем. Поэтому команда хорошо работает с электронными книгами, отчётами, счетами и инструкциями, где символы действительно записаны в PDF, но ничего не найдёт на фотографии страницы без OCR. Это различие полезно проверить в самом начале: если текст можно выделить в обычном просмотрщике, вероятность успешного поиска высока; если выделяется только вся страница как картинка, сначала потребуется распознавание.
По умолчанию шаблон трактуется как расширенное регулярное выражение. Это значит, что точка, квадратные скобки, звёздочка, плюс и некоторые другие знаки имеют специальный смысл. Для буквального поиска номера договора, артикула или строки с символами пунктуации безопаснее включать -F. Для более сложных конструкций доступен режим PCRE2 через -P, если пакет был собран с соответствующей библиотекой. Выбор режима влияет не на извлечение текста, а на то, как уже извлечённая строка сравнивается с запросом.
Результат печатается в стандартный вывод, сообщения об ошибках — в стандартный поток ошибок. Такое разделение важно в автоматизации: найденные строки можно записать в файл или передать следующей команде, а предупреждения о повреждённом либо пустом документе останутся заметными отдельно. Код завершения дополнительно сообщает, было ли хотя бы одно совпадение, не нашлось ли ничего или произошла ошибка.

Установка и проверка готовности
В Linux удобнее устанавливать пакет из репозитория дистрибутива, поскольку вместе с исполняемым файлом подтягиваются совместимые сборки Poppler, libgcrypt и PCRE2. Для систем семейства Debian команда обычно выглядит как sudo apt install pdfgrep, в Fedora используется sudo dnf install pdfgrep, а в Arch Linux — sudo pacman -S pdfgrep. Название пакета совпадает с именем команды, поэтому после установки не нужно искать отдельный запускатель.
В macOS пакет доступен через Homebrew и MacPorts. В системах BSD используются коллекции портов или готовые бинарные пакеты. На Windows практичнее работать в WSL или Cygwin: синтаксис оболочки, кавычки, конвейеры и пути в таком окружении ведут себя предсказуемее, чем при попытке переносить Unix-команды в обычную командную строку. Для сценариев, где нужен визуальный поиск и редактирование, терминальная схема может оказаться неоправданно сложной.
Первая проверка не должна зависеть от конкретного документа. Команда pdfgrep --version показывает, что исполняемый файл запускается, а pdfgrep --help выводит краткий перечень параметров. Если оболочка отвечает command not found, проблема находится на уровне установки или переменной PATH, а не в PDF. Если справка открывается, но поиск завершается сообщением о библиотеке, следует проверить целостность пакета и не смешаны ли файлы из разных репозиториев.
pdfgrep --version
pdfgrep --help
pdfgrep "test" sample.pdf
При сборке из исходного пакета используются обычные этапы ./configure, make и sudo make install. До этого понадобятся заголовочные пакеты Poppler C++, libgcrypt и, при необходимости, PCRE2. Отсутствие PCRE2 не мешает базовому поиску, но параметр -P будет недоступен; экспериментальное удаление диакритики также появляется только в сборке с libunac.

Базовый синтаксис без ошибок оболочки
Минимальная форма состоит из шаблона и хотя бы одного файла: pdfgrep ШАБЛОН ФАЙЛ. Пробелы внутри фразы требуют кавычек, иначе оболочка разделит запрос на несколько аргументов и первый лишний фрагмент будет принят за имя документа. Для русского текста подходят обычные одинарные или двойные кавычки в локали UTF-8. Одинарные кавычки почти всегда безопаснее, потому что оболочка не подставляет внутри них переменные и специальные последовательности.
Шаблон, начинающийся с дефиса, нужно передавать через -e или отделять параметры двойным дефисом. Например, поиск строки -draft записывают как pdfgrep -F -e '-draft' file.pdf. Без -e программа попробует прочитать слово как опцию. Такой же приём полезен в скриптах, когда запрос поступает от пользователя и заранее неизвестно, с какого символа он начнётся.
Имена файлов с пробелами заключают в кавычки отдельно от шаблона. Конструкция pdfgrep 'срок оплаты' 'Договор поставки.pdf' передаёт два аргумента именно в ожидаемом виде. При обработке списка лучше избегать цикла по результату ls: пробелы и переносы строк разрушат границы имён. Надёжные варианты используют массив оболочки, маску *.pdf либо нулевые разделители find -print0 и xargs -0.
Обычная маска раскрывается оболочкой до запуска pdfgrep. Команда pdfgrep -H 'ГОСТ' *.pdf получит готовый список файлов из текущей папки. Если совпадений по маске нет, поведение зависит от оболочки: она может передать буквальную строку *.pdf, после чего появится ошибка открытия файла. В сценариях стоит заранее включать подходящую настройку оболочки или использовать рекурсивный режим с --include.

Поиск в одном документе
Для одного файла имя обычно не печатается, потому что оно и так известно. Вывод содержит строку извлечённого текста, а совпавшая часть подсвечивается при работе в интерактивном терминале. Если результат отправить в файл, цвет по умолчанию отключится, чтобы управляющие последовательности не портили текст. Принудительное поведение задаётся как --color=always, --color=never или --color=auto.
Проверку лучше начинать с короткого уникального фрагмента без пунктуации. Если он находится, запрос постепенно расширяют до нужной фразы. Это помогает отличить проблему извлечения текста от слишком строгого шаблона. Переносы, разрывы слов и особенности вёрстки могут разделить визуально непрерывную фразу на несколько строк, поэтому точное длинное предложение часто оказывается менее надёжным, чем два коротких независимых признака.
Опция -i снимает различие регистра. Она полезна для заголовков, аббревиатур и фамилий, которые встречаются в разных написаниях. При этом различия символов, зависящие от Unicode и локали, определяются возможностями регулярного движка и тем, какой текст вернул Poppler. Для юридических номеров и кодов регистр обычно значим, поэтому включать -i автоматически не стоит.
pdfgrep 'неустойка' contract.pdf
pdfgrep -i 'неустойка' contract.pdf
pdfgrep -F 'A-17/2026' contract.pdf
Если нужно увидеть только совпавший кусок без окружающей строки, используется -o. Этот режим удобен для извлечения идентификаторов, адресов электронной почты, номеров заявок и других компактных значений. Каждое совпадение печатается отдельно, поэтому строка с тремя номерами даст три строки результата. Контекстные параметры одновременно с -o смысла не имеют и игнорируются.

Работа с несколькими PDF
Когда передано два и более документа, перед каждой найденной строкой появляется имя файла. Параметр -H заставляет показывать его даже при единственном входном файле, а -h скрывает префикс. Для последующей сортировки и отчёта лучше явно задавать -H: тогда формат результата не изменится, если список входных файлов случайно сократится до одного.
Шаблон оболочки подходит для неглубокой папки: pdfgrep -Hn 'серийный номер' reports/*.pdf. Здесь -n добавляет страницу. Если документов много, строка вывода становится самодостаточной: по ней можно открыть нужный файл и перейти к указанной странице. В именах с двоеточием визуальный разделитель может быть неоднозначен; для интерактивной работы его меняют через --match-prefix-separator, а для машинной обработки используют нулевой байт.
Список файлов можно формировать отдельной командой, но передача через обычный пробел безопасна только для простых имён. Универсальная конструкция применяет find с -print0 и xargs -0. Она сохраняет пробелы, кавычки и переводы строк в имени. Поскольку сам pdfgrep умеет рекурсивный обход, внешняя связка нужна главным образом для условий, которых у него нет: ограничения по размеру, дате изменения, владельцу или расположению.
pdfgrep -Hn -i 'акт приёмки' *.pdf
find archive -type f -name '*.pdf' -size -20M -print0 |
xargs -0 pdfgrep -Hn -F 'ИНН 7701234567'
Если нужно только определить, какие документы содержат фразу, параметр -l печатает по одному имени файла. Обратный режим -L перечисляет документы без совпадения. Эти варианты экономят объём вывода и удобны для проверки комплектности: например, можно найти все отчёты, где отсутствует обязательная формулировка, не просматривая сотни строк контекста.
Номера страниц и метки страниц
Параметр -n выводит номер страницы перед совпадением. В отличие от обычного grep, здесь речь идёт не о номере строки исходного файла, а об индексе страницы PDF, начиная с единицы. Это наиболее практичный ориентир для открытия результата в просмотрщике. Несколько совпадений на одной странице могут появиться с одинаковым номером, потому что каждая подходящая строка печатается отдельно.
В некоторых книгах и отчётах печатная нумерация не совпадает с физическим порядком страниц: вступление помечено римскими цифрами, приложения имеют буквенные обозначения, а обложка не входит в счёт. Если в PDF сохранены метки страниц, режим --page-number=label выводит именно их. Когда меток нет или они заданы некорректно, надёжнее использовать обычный индекс и сверяться с навигацией просмотрщика.
Опция -p, также называемая --page-count, не печатает сам текст, а показывает число совпадений на каждой затронутой странице. Она автоматически включает номера страниц. Это помогает быстро увидеть, где термин обсуждается подробно, а где упомянут один раз. Следует помнить, что считается каждое совпадение, а не число строк: два вхождения шаблона в одной строке увеличат счётчик на два.

Для сводки по всему документу используется -c. Он выдаёт общее количество совпадений на файл. Если нужен именно перечень страниц без текста, можно совместить -n и обработку вывода внешними командами, но -p обычно проще и не теряет информацию о количестве вхождений.

Рекурсивный обход каталогов
Ключ -r запускает поиск во всех подходящих PDF внутри указанных каталогов. Если путь не задан, используется текущая папка. Символические ссылки, встреченные во время обхода, не разворачиваются; ссылки, явно переданные в командной строке, обрабатываются. Режим -R следует всем символическим ссылкам, поэтому в сложном дереве способен повторно зайти в те же каталоги или пройти значительно больше данных, чем ожидалось.
Фильтр --include ограничивает имена файлов glob-маской, --exclude исключает совпавшие базовые имена. Эти параметры применяются к объектам, найденным рекурсивно, а не к файлам, перечисленным вручную. По умолчанию рекурсивный режим принимает расширение PDF в разных сочетаниях регистра. Несколько --exclude можно повторять; исключение имеет приоритет над включением.
pdfgrep -rHn 'конфиденциально' documents
pdfgrep -rHn --include 'invoice-*.pdf' 'VAT' accounting
pdfgrep -rHn --exclude '*draft*' --exclude '*old*' 'утверждено' .
Маска сопоставляется с именем, а не с полным путём. Поэтому исключить конкретную ветвь дерева одним шаблоном пути нельзя так же гибко, как в find. Если структура важнее имён файлов, сначала отберите документы внешней командой. Аналогично, pdfgrep не имеет собственного условия по размеру, времени изменения или глубине; эти ограничения следует применять до передачи файлов.
Перед большим рекурсивным поиском полезно выполнить -l или -m 1 на небольшой подпапке. Так легче обнаружить неожиданно включённые резервные копии, сетевые точки и каталоги сборки. Режим -R стоит выбирать только при осознанной необходимости следовать ссылкам, иначе безопаснее -r.
Точные строки и регулярные выражения
В режиме по умолчанию используются расширенные POSIX-выражения. Квадратные скобки описывают набор символов, круглые скобки группируют части, вертикальная черта задаёт альтернативу, а квантификаторы управляют повторением. Например, 'договор|контракт' находит оба слова, а '№[[:space:]]*[0-9]+' допускает произвольный пробел после знака номера. Сам шаблон следует заключать в одинарные кавычки, чтобы оболочка не интерпретировала звёздочки и скобки.
Режим -F воспринимает каждую строку шаблона буквально. Это оптимальный выбор для контрольных сумм, имён функций, путей, маркировок, артикулов и фраз с точками или плюсами. Он также снижает риск ошибки регулярного выражения, когда данные поступают из внешней системы. Несколько строк внутри шаблона означают набор альтернатив: совпадение любой из них считается успешным.
PCRE2 включается параметром -P. Он нужен для привычных Perl-совместимых конструкций, более выразительных классов и некоторых видов просмотра вперёд или назад. Доступность зависит от сборки. Если команда сообщает, что PCRE не поддерживается, следует либо установить пакет дистрибутива с этой возможностью, либо переписать выражение в POSIX-форме, либо использовать несколько простых проходов.
Нельзя рассчитывать, что регулярное выражение увидит визуальную структуру страницы. Табличные колонки, колонтитулы и переносы могут быть извлечены в неожиданном порядке. Шаблон работает по строкам, полученным от Poppler; переход через границу строки не совпадёт с обычной точкой или пробелом. Для сложной таблицы сначала полезно посмотреть результат pdftotext -layout и понять, как именно закодирован текст.
pdfgrep -F 'C++17' manual.pdf
pdfgrep -i 'договор|контракт' *.pdf
pdfgrep -P '\b[A-Z]{2}-\d{6}\b' registry.pdf
Несколько шаблонов и файл запросов
Опция -e задаёт шаблон явно и может повторяться. Все шаблоны объединяются логическим ИЛИ: строка выводится, если подошёл хотя бы один. Такой способ удобнее громоздкой альтернативы, особенно когда часть запросов должна быть буквальной или начинается с дефиса. Однако режим интерпретации — обычный, -F или -P — общий для всего вызова.
Параметр -f читает шаблоны из текстового файла, по одному на строку. Можно указать несколько файлов и одновременно добавить -e. Пустой список шаблонов ничего не находит. Файл следует сохранять в кодировке, соответствующей локали терминала, обычно UTF-8; невидимый символ возврата каретки после переноса Windows может стать частью шаблона в окружениях, где строки не нормализуются.
pdfgrep -Hn -e 'ошибка' -e 'предупреждение' logs.pdf
pdfgrep -F -f required_phrases.txt contracts/*.pdf
pdfgrep -i -f surnames.txt archive/*.pdf
Большой список запросов лучше сначала проверить на небольшом документе. Слишком общая строка, например одиночная буква или распространённый предлог, создаст огромный вывод и замедлит обработку. Для аудита обязательных формулировок часто нужен не один поиск с ИЛИ, а отдельный проход для каждой фразы: общий вызов показывает наличие любой, но не доказывает присутствие всех.
Если шаблоны поступают из таблицы или базы, их стоит очистить от пустых строк, завершающих пробелов и дубликатов. Для буквального режима это особенно важно: пробел в конце станет обязательной частью строки. Регулярные выражения желательно хранить отдельно от обычных фраз, чтобы пользователь случайно не включил -F и не превратил метасимволы в буквальный текст.
Регистр, диакритика, лигатуры и Unicode
Нечувствительность к регистру включается ключом -i и применяется одновременно к шаблону и тексту PDF. Корректность для национальных алфавитов зависит от локали процесса и того, как Poppler декодировал шрифтовые таблицы. Если латиница находится, а кириллица нет, сначала проверьте locale: значения семейства UTF-8 обычно необходимы для ожидаемого поведения.
В PDF один визуальный знак может быть записан необычным кодом. Частая проблема — лигатуры вроде fi и fl: слово выглядит нормально, но последовательности отдельных букв внутри нет. Экспериментальная опция --unac удаляет диакритические знаки и нормализует некоторые лигатуры в шаблоне и документе, однако присутствует только в сборках с libunac. Рассчитывать на неё в переносимом скрипте нельзя без предварительной проверки pdfgrep --help.
Дефисы и тире тоже различаются. В документах встречаются обычный минус, неразрывный дефис, короткое и длинное тире. Буквальный запрос совпадёт только с тем кодовым знаком, который реально извлечён. Для устойчивого выражения можно перечислить варианты в классе символов или искать соседние слова отдельно. То же относится к неразрывному пробелу и типографским кавычкам.
Если текст копируется из PDF в терминал, вместе с ним иногда попадают скрытые переносы или управляющие символы. Надёжнее набрать короткий шаблон вручную, а затем при необходимости исследовать вывод pdftotext через шестнадцатеричный просмотр. Ошибка не всегда находится в pdfgrep: программа сопоставляет именно ту последовательность, которую ей вернула библиотека извлечения.
Контекст вокруг совпадения
Параметр -A N печатает N строк после совпавшей, -B N — N строк до неё, а -C N — одинаковое число с обеих сторон. Контекст относится к строкам извлечённого текста, а не к визуальным строкам в макете страницы. В многоколоночном документе соседняя строка в потоке может принадлежать другой колонке, поэтому результат нужно оценивать по конкретному файлу.
Перекрывающиеся области контекста объединяются, чтобы одна и та же строка не повторялась. Раздельные группы отделяются строкой с двумя дефисами. Такой формат близок к GNU grep и удобен для чтения, но при машинном разборе следует учитывать разделители. Если требуется только значение, используйте -o; если нужен фрагмент для человека, контекст обычно полезнее.

Контекст после совпадения подходит для терминов, за которыми следует определение или значение. Контекст до совпадения помогает увидеть заголовок, имя раздела либо начало предложения. Симметричный вариант удобен при первичном исследовании незнакомого документа.

При поиске конфиденциальных данных будьте осторожны с большим контекстом: вместе с нужной строкой в журнал или отчёт могут попасть соседние персональные сведения. Для автоматизированной проверки наличия фразы лучше -q, для извлечения идентификатора — -o, а подробный контекст оставлять интерактивной диагностике.

Подсчёт, ограничение и краткие результаты
Ключ -c подавляет обычные строки и выдаёт количество совпадений для каждого входного файла. Подсчёт ведётся по вхождениям, а не по страницам или строкам. Если одна строка содержит шаблон дважды, счётчик увеличится на два. Для оценки числа затронутых страниц используйте -p, а для числа документов — -l и внешнюю команду подсчёта строк.

Опция -m N прекращает чтение очередного файла после N найденных совпадений. Ограничение применяется к каждому файлу отдельно. Вместе с -c результат не превысит N, поэтому такая комбинация отвечает на вопрос есть ли как минимум несколько совпадений, но не даёт полного количества. Для быстрого теста наличия достаточно -m 1 или -q.
Режим -q ничего не печатает и завершает работу с кодом ноль сразу после первого совпадения. Он предназначен для условий в shell-скриптах. Особенность: если совпадение уже найдено, код ноль возвращается даже при ошибках в других входных файлах. Когда важно одновременно доказать отсутствие ошибок во всей коллекции, не следует скрывать вывод и преждевременно завершать поиск.
if pdfgrep -q -F 'УТВЕРЖДАЮ' report.pdf; then
echo 'Метка найдена'
else
echo 'Метка отсутствует или файл не прочитан'
fi
Чтобы различить отсутствие совпадения и техническую ошибку, проверяйте точный код завершения: ноль означает найденный шаблон, единица — корректно обработанные файлы без совпадений, двойка — ошибку. В сложных сценариях сохраните код сразу после вызова, потому что следующая команда перезапишет переменную $?.
Ограничение поиска страницами
Опция --page-range принимает список отдельных страниц и диапазонов через запятую. Запись 2-3,5,7-10 проверяет страницы 2, 3, 5 и 7–10. Это снижает объём работы, если нужная информация всегда находится в приложении, титульной части или определённом разделе. Нумерация относится к физическому индексу страниц, а не к печатным меткам.
Диапазон особенно полезен для унифицированных форм: искать подпись только на последней странице, код документа — в шапке, а таблицу согласований — в приложении. Однако документы с разным количеством вставок могут сместить нужный раздел. Перед массовой проверкой убедитесь, что шаблон верстки действительно стабилен, иначе ограничение создаст ложные отрицательные результаты.
pdfgrep --page-range=1-2 -Hn 'Регистрационный номер' *.pdf
pdfgrep --page-range=20-30 -i 'приложение' manual.pdf
pdfgrep --page-range=2-3,5,7-10 -F 'контрольная точка' report.pdf
Сочетание диапазона с кэшем ускоряет повторные запросы по большим документам, но кэш хранит извлечённый текст, а не готовые ответы. Новый шаблон всё равно сопоставляется заново. Если диапазон задан неверно или выходит за пределы документа, полезно повторить запрос без ограничения и сравнить результат.
PDF, защищённые паролем
Параметр --password=ПАРОЛЬ передаёт пароль для открытия зашифрованного документа. Опцию можно повторить: каждый указанный пароль пробуется для всех входных PDF. Это удобно для набора документов с несколькими известными паролями, но число попыток растёт как произведение файлов и паролей.
Пароль, записанный в командной строке, может сохраниться в истории оболочки и быть виден другим процессам через список запущенных команд. Официальная справка прямо предупреждает об этом риске. Для чувствительных данных лучше временно отключить запись истории, запускать команду в изолированной сессии или предварительно снять защиту разрешённым инструментом в безопасном каталоге. Передача секрета через аргумент нельзя считать защищённым каналом.
Если пароль неверен, документ не будет прочитан и появится сообщение об ошибке. Пустой результат в такой ситуации не означает отсутствие фразы. В скрипте необходимо контролировать код завершения и стандартный поток ошибок. Также важно различать пароль владельца и пароль пользователя: возможность извлечения текста зависит от того, может ли Poppler открыть файл с предоставленными данными и ограничениями.
pdfgrep --password='temporary-pass' -Hn 'invoice' protected.pdf
Не помещайте реальный пароль в общий журнал, файл примеров или систему мониторинга команд. Если требуется регулярная обработка защищённых документов, лучше пересмотреть процесс хранения: автоматизация с секретом в аргументах удобна, но оставляет слишком много следов.
Почему поиск не работает в сканах
Сканированный PDF часто содержит только изображения страниц. pdfgrep не выполняет распознавание символов и потому не может превратить фотографию текста в слова. Ключ --warn-empty просит вывести предупреждение, если документ не содержит доступного поискового текста. Это помогает отличить настоящий нулевой результат от файла, в котором искать было нечего.
Перед поиском такой документ нужно пропустить через OCR-программу, сохраняющую распознанный слой в PDF. Подходящий процесс состоит из четырёх этапов: проверить ориентацию и качество страниц, распознать нужные языки, сохранить PDF с текстовым слоем, затем повторить короткий тестовый запрос. Низкое качество скана, неверный язык и таблицы могут дать ошибки, поэтому критичные совпадения следует подтверждать визуально.
Иногда текстовый слой присутствует только на части страниц. Тогда pdfgrep найдёт слова в электронных разделах и промолчит на сканированных вставках. --warn-empty оценивает документ в рамках доступного извлечения, но не заменяет покомпонентную проверку. При миграции коллекции полезно отдельно измерять долю страниц с текстом средствами OCR-конвейера.
Неудачное распознавание меняет буквы на похожие знаки: ноль на О, латинскую C на кириллическую С, единицу на I. Точный -F в этом случае слишком строг. Можно искать устойчивую часть слова, использовать несколько вариантов через -e или исправить OCR. Регулярное выражение не восстанавливает отсутствующий смысл, а лишь описывает допустимые ошибки.
Кэш и скорость повторных запросов
Параметр --cache сохраняет извлечённый текст и при следующем поиске может не разбирать PDF заново. Выигрыш заметен на больших документах и при серии разных запросов по одной коллекции. Кэш размещается в каталоге, определяемом XDG_CACHE_HOME, либо в стандартном пользовательском пути. Справка указывает, что старые записи обслуживаются автоматически и число долгоживущих элементов ограничивается.

Первый запуск с кэшем включает стоимость извлечения и записи, поэтому может быть не быстрее обычного. Преимущество проявляется со второго запроса. Измерять следует одинаковые команды на одном наборе файлов, очищая влияние дискового кэша операционной системы только если нужен строгий тест. В повседневной работе важнее субъективная задержка и повторяемость.
Кэш не является полнотекстовым индексом уровня Recoll. Он сокращает этап преобразования PDF в текст, но каждый новый шаблон всё равно проверяется по сохранённому содержимому. Для миллионов документов с постоянными запросами индексирующая система масштабируется лучше. Для десятков или сотен часто открываемых руководств --cache даёт преимущество без настройки отдельной базы.
После изменения PDF корректность зависит от механизма идентификации записи. Если возникают подозрения на устаревший результат, сравните поиск без --cache и при необходимости удалите пользовательский каталог кэша pdfgrep. Не стоит очищать весь системный кэш без разбора. В автоматизации фиксируйте, включён ли кэш, чтобы время разных запусков было сопоставимо.
Параллельная обработка через GNU Parallel способна ускорить коллекцию на многоядерном процессоре, потому что каждый файл проверяется отдельным процессом. Однако чрезмерное число задач увеличивает нагрузку на диск и память. Начинайте с числа потоков, близкого к количеству физических ядер, и измеряйте. На сетевом хранилище узким местом чаще становится ввод-вывод, а не регулярное выражение.
Конвейеры, нулевые разделители и автоматизация
Опция -Z заменяет двоеточие после имени файла нулевым байтом. Она нужна не для красоты вывода, а для однозначной передачи имён, которые могут содержать пробелы, двоеточия или переводы строк. Типичный сценарий сначала получает список документов через --files-with-matches, затем передаёт его xargs -0 во второй поиск.
pdfgrep -Z -l 'приложение' *.pdf |
xargs -0 pdfgrep -Hn 'подпись'
Такой двухступенчатый запрос находит вторую фразу только в документах, где есть первая. Это логическое И на уровне файла, а не строки. Одна команда с двумя -e дала бы ИЛИ и не решила задачу. Нулевой разделитель сохраняет корректность даже для необычных имён.
Для поиска по условию размера официальная документация предлагает сочетать find, -print0 и xargs -0. Аналогично можно отобрать файлы новее определённой даты, исключить точки монтирования или ограничить глубину. pdfgrep концентрируется на тексте PDF, а файловые условия делегируются специализированным утилитам.
find . -name '*.pdf' -size -12M -print0 |
xargs -0 pdfgrep -Hn 'контроль'
При параллельном запуске добавляйте -H, иначе строки разных процессов невозможно будет связать с файлами. Для детерминированного отчёта результат затем сортируют. Цвет лучше отключить через --color=never, поскольку управляющие коды затрудняют сравнение и разбор.
В скриптах не анализируйте человеческие сообщения, если достаточно кода завершения. Текст ошибок может меняться или зависеть от языка окружения. Для протокола сохраняйте отдельно стандартный вывод, стандартный поток ошибок и код. Это позволяет отличить совпадений нет от часть файлов не прочитана.
Цвет и формат результата
В интерактивном терминале совпадение обычно подсвечивается автоматически. Кроме текста, цветом могут оформляться имя файла, номер страницы и разделители. Переменная окружения GREP_COLORS использует знакомый синтаксис GNU grep; pdfgrep учитывает возможности для совпадения, имени файла, номера и разделителя. Это позволяет согласовать вывод с тёмной или светлой темой.
При перенаправлении в файл режим auto отключает цвет. Для последующей обработки это правильно. Если цвет был принудительно включён, в тексте появятся ANSI-последовательности, которые выглядят как лишние символы и ломают регулярные выражения. В отчётных командах явно задавайте --color=never.
Префиксы обычно разделяются двоеточием. Параметр --match-prefix-separator меняет этот знак на произвольную строку и подходит для чтения человеком, когда сами имена содержат двоеточия. Для надёжного машинного протокола лучше -Z, потому что любой печатный разделитель теоретически может встретиться в имени или тексте.
Длинные извлечённые строки могут переноситься самим терминалом, хотя pdfgrep считает их одной строкой. При копировании это создаёт впечатление дополнительных переводов. Запись в файл с последующим просмотром через less -S помогает увидеть реальную структуру. Если требуется табличный отчёт, сначала отключите цвет и выберите однозначный способ отделения метаданных.
Коды завершения и надёжные shell-условия
Нулевой код означает, что хотя бы одно совпадение найдено. Единица сообщает, что обработка завершилась, но шаблон не встретился. Двойка обозначает ошибку. Это соглашение позволяет использовать pdfgrep непосредственно в if, но требует аккуратности с режимом -q: после раннего совпадения он может не сообщить об ошибке в другом файле.
pdfgrep -q -F 'Оплачено' invoice.pdf
status=$?
case "$status" in
0) echo 'Совпадение есть' ;;
1) echo 'Совпадения нет' ;;
2) echo 'Ошибка чтения' >&2 ;;
esac
В оболочке с set -e код единица может неожиданно остановить сценарий, хотя отсутствие совпадения является нормальной ветвью. Помещайте вызов прямо в условие или временно обрабатывайте код вручную. Не добавляйте бездумно || true: оно скроет и код двойка, лишив вас информации о повреждённом файле.
В конвейере итоговый код по умолчанию часто принадлежит последней команде. Если результат pdfgrep передан в sort, ошибка поиска может потеряться. В Bash включите set -o pipefail или сохраните элементы массива PIPESTATUS. Для критичного аудита лучше сначала записать вывод во временный файл, проверить статус, затем сортировать.
Проверка сотен документов должна учитывать частичный успех. Одна повреждённая копия не делает остальные результаты ложными, но отчёт обязан перечислить непрочитанные файлы. Храните диагностический поток отдельно и не выдавайте нулевое число совпадений за доказательство отсутствия фразы, пока код завершения указывает на ошибку.
Типичные ошибки и способы исправления
Команда не найдена
Проверьте установку пакета и PATH. Запуск справки по полному пути помогает понять, существует ли исполняемый файл. Не скачивайте случайный бинарник с неизвестного сайта только ради устранения ошибки оболочки: зависимости Poppler и PCRE2 должны соответствовать системе.
Файл не открывается
Убедитесь, что путь заключён в кавычки, регистр букв совпадает, а у пользователя есть права чтения. Для символической ссылки проверьте целевой объект. Сообщение об ошибке пароля требует корректного --password; повреждённый PDF стоит открыть другим инструментом и при необходимости пересохранить.
Совпадений нет, хотя слово видно
Сначала попробуйте короткую часть слова с -i. Затем проверьте, выделяется ли текст в просмотрщике и что возвращает pdftotext. Причинами бывают скан без OCR, лигатура, неразрывный пробел, другой дефис, разрыв строки, нестандартная карта символов или неверная локаль.
Регулярное выражение выдаёт ошибку
Заключите шаблон в одинарные кавычки и проверьте парность скобок. Для буквальной строки включите -F. Если выражение рассчитано на PCRE2, добавьте -P и убедитесь, что поддержка присутствует. Конструкции разных движков не полностью взаимозаменяемы.
Результат слишком большой
Ограничьте страницы, файлы и число совпадений. Используйте -l, -c, -p, -m или более точный шаблон. Отключите контекст и проверьте, не попали ли в рекурсивный обход резервные копии. Для интерактивного просмотра передайте вывод в less, но не забывайте про pipefail в скрипте.
Цветовые коды попали в файл
Укажите --color=never. Автоматический режим обычно сам отключает оформление при перенаправлении, но алиас или переменная окружения могут изменить поведение. Перед машинным разбором всегда задавайте формат явно.
Практические сценарии
Проверка договоров
Сначала ищут обязательную формулировку через -F -l, затем отдельным проходом получают документы без неё через -L. Номера страниц добавляют только в подробный отчёт. Для нескольких обязательных пунктов запускают независимые проверки, потому что общий список -e подтверждает наличие любой фразы, а не всех сразу.
Поиск в технической библиотеке
Рекурсивный режим с -iHn быстро находит параметр, код ошибки или название интерфейса во множестве руководств. --include отделяет официальные документы от приложений, --cache ускоряет последующие запросы. Для кода и имён функций лучше -F, чтобы круглые скобки и плюсы не стали метасимволами.
Аудит счетов и актов
Регулярное выражение может извлекать номера, даты и идентификаторы через -o. Затем строки нормализуют и сравнивают с реестром. Точность зависит от исходного текстового слоя: сканы сначала распознаются, а результаты OCR проверяются по контрольной выборке. Денежные суммы нельзя считать надёжно извлечёнными без учёта разделителей разрядов и локальных форматов.
Работа с научными статьями
Поиск по каталогу с -l формирует короткий список релевантных публикаций, -nC 2 показывает контекст и страницу. Термины с дефисами и греческими символами проверяют в нескольких написаниях. pdfgrep не выполняет смысловой поиск: синонимы, формы слова и перевод нужно перечислить явно.
Контроль документации сборки
Скрипт может проверять, что экспортированные PDF содержат номер редакции, предупреждение и контакт. Коды завершения интегрируются в CI. Однако визуальная корректность, шрифты и расположение элементов остаются вне области pdfgrep; для них нужны рендеринг и сравнение страниц.
Ограничения формата PDF
Порядок текста в PDF определяется внутренними объектами, а не только тем, что видно на экране. Две колонки могут извлекаться по строкам попеременно, подпись рисунка — раньше заголовка, колонтитул — между абзацами. Поэтому контекст представляет логический поток Poppler и не гарантирует визуальную близость.
Текст внутри кривых, растровых изображений и некоторых встроенных объектов недоступен без распознавания. Аннотации, формы, вложения и метаданные не следует считать частью обычного страничного текста, если документация явно не подтверждает их извлечение. pdfgrep предназначен для поискового текстового слоя страниц, а не для полного анализа всех структур PDF.
Повреждённые шрифтовые карты могут превращать видимые буквы в пустые или ошибочные символы. Пересохранение документа через другой PDF-принтер иногда улучшает извлечение, но способно изменить качество, ссылки и подписи. Для подписанных документов нельзя пересохранять файл без понимания юридических последствий.
Очень большие PDF обрабатываются постранично, но извлечение всё равно требует процессорного времени и памяти. Кэш сокращает повторную работу, диапазон страниц уменьшает объём, а параллелизм помогает коллекциям. Если один файл стабильно приводит к сбою, изолируйте его и проверьте утилитами Poppler; не запускайте бесконечные повторные попытки внутри общего цикла.
Безопасность и конфиденциальность
Во время поиска содержимое документов остаётся в файловой системе, а результат записывается только в выбранные потоки. Однако строки терминала, история оболочки, журналы CI и перенаправленные файлы могут сохранять найденные персональные данные. Минимизируйте контекст, защищайте права на отчёты и очищайте временные файлы по принятой политике.
Пароль в параметре командной строки — наиболее заметный риск. Он доступен истории и может отображаться в списке процессов. Не используйте этот механизм для высокочувствительных секретов без компенсирующих мер. Кэш также содержит извлечённый текст; права на каталог и политика очистки должны соответствовать уровню документов.
При обработке файлов из недоверенного происхождения используйте обновлённые системные библиотеки и изолированную учётную запись. pdfgrep полагается на Poppler для разбора сложного формата, поэтому безопасность зависит не только от самой команды. Ограничение ресурсов и работа в контейнере снижают последствия повреждённого файла.
Результат поиска не доказывает подлинность документа. Он лишь показывает совпадение в доступном текстовом слое. Электронные подписи, целостность, временные метки и права доступа проверяются отдельными средствами.
Справочник по режимам результата
Перед запуском полезно сформулировать, какой объект должен оказаться в результате: строка, отдельное совпадение, страница, документ или только код успеха. Обычный вывод сохраняет всю извлечённую строку и подходит для чтения человеком. -o оставляет только совпавший фрагмент и удобен для извлечения идентификаторов. -n добавляет страницу, -H — имя файла, -c считает все вхождения, -p группирует счёт по страницам, -l и -L возвращают списки документов, а -q сообщает только факт совпадения через код завершения.
| Задача | Основной параметр | Что появляется в выводе |
|---|---|---|
| Прочитать найденный фрагмент | Без специального режима | Полная строка с выделенным совпадением |
| Узнать страницу | -n | Индекс или метка страницы перед строкой |
| Извлечь номер или код | -o | Только часть, совпавшая с шаблоном |
| Посчитать все вхождения | -c | Одно число для каждого файла |
| Посчитать по страницам | -p | Страница и число совпадений на ней |
| Получить документы с фразой | -l | Только имена подходящих файлов |
| Получить документы без фразы | -L | Только имена файлов без совпадений |
| Проверить условие в скрипте | -q | Ничего; используется код завершения |
Режимы нельзя считать взаимозаменяемыми. -c отвечает на вопрос о количестве вхождений, а не строк или страниц: два совпадения в одной строке учитываются отдельно. -p показывает число совпадений для каждой затронутой страницы и автоматически включает номер страницы. -l прекращает обычную печать строк и игнорирует параметры, которые не имеют смысла для списка файлов. Поэтому команда для аналитического отчёта обычно строится не путём добавления всех ключей сразу, а несколькими независимыми проходами.
Для машинного результата имя файла нужно задавать явно через -H, даже если текущий тест выполняется с несколькими документами и префикс появляется автоматически. После изменения количества аргументов автоматическое правило может поменять формат. Аналогично, -h удобно для интерактивной работы с одним документом, но в общем отчёте оно удаляет важную связь между строкой и файлом.
Сочетание -o с контекстом не даёт соседних строк: параметры -A, -B и -C в таком режиме не действуют. Сначала решите, нужен ли точный извлекаемый токен или читаемый фрагмент. Для реестра номеров выбирают -o, для проверки смысла предложения — полную строку с контекстом, а для ручного перехода в просмотрщик — номер страницы.
Индекс страницы и печатная метка
Параметр -n по умолчанию выводит индекс страницы, начиная с единицы. Это физическая позиция листа внутри PDF и наиболее устойчивый ориентир для автоматизации. Если команда показала страницу 12, речь идёт о двенадцатом объекте страницы в файле независимо от того, какой номер напечатан в колонтитуле.
Форма --page-number=label вместо индекса использует метку, записанную создателем PDF. Метка может быть римским числом во вступлении, обычным арабским номером в основной части, буквенным приложением или произвольной строкой. Такой вывод удобнее человеку, когда просмотрщик тоже показывает метки, но он хуже подходит для арифметики и сортировки: значения iv, 1, A-2 нельзя надёжно сравнивать как обычные числа.
Метка не извлекается из видимого колонтитула. Если автор документа не настроил таблицу меток, pdfgrep не угадывает напечатанный номер. После вставки обложки или приложения физический индекс и номер в тексте могут расходиться. В отчёте стоит заранее указать, какой тип используется, иначе пользователь откроет страницу 8 по счётчику просмотрщика и попадёт на другой лист.
pdfgrep -Hn -F 'Область применения' standards/*.pdf
pdfgrep -H --page-number=label -F 'Область применения' standards/*.pdf
Для перехода из скрипта в просмотрщик чаще нужен индекс. Для отчёта, который сверяется с оглавлением печатного документа, может оказаться полезнее метка. Если коллекция содержит файлы с разными правилами нумерации, безопаснее сохранить оба отчёта либо использовать индекс как технический ключ, а метку — как дополнительное поле, полученное отдельным проходом.
Ограничение --page-range использует номера страниц в диапазоне, а не строковые метки. Список записывается через запятые, отдельные интервалы — через дефис, например 2-3,5,7-10. Перед массовым запуском проверьте диапазон на одном известном файле: если документ имеет обложку и введение, нужный печатный раздел может начинаться не с ожидаемого физического индекса.
Диагностика PDF без доступного текста
Опция --warn-empty печатает предупреждение в стандартный поток ошибок, когда в PDF нет поискового текста. Она особенно полезна при пакетной проверке: без неё пустой скан внешне похож на обычный документ, где фраза просто отсутствует. Включение предупреждения не создаёт OCR и не меняет результат, но позволяет отделить технически непоисковые файлы от отрицательных совпадений.
pdfgrep --warn-empty -Hn -F 'серийный номер' incoming/*.pdf \
>matches.txt 2>diagnostics.txt
Файл диагностик следует анализировать отдельно. Предупреждение о пустом тексте означает, что вывод не найдено нельзя использовать как содержательный вывод. Ошибка открытия, неверный пароль и повреждение файла также требуют отдельного статуса. В контроле обязательной формулировки разумно иметь три категории: найдено, корректно прочитано без совпадения, невозможно проверить.
Параметр --debug добавляет техническую информацию и нужен при разборе сбоя, а не в постоянном отчёте. Отладочный поток может быть большим и зависеть от версии библиотек. Сначала воспроизведите проблему на одном файле, отключите цвет, перенаправьте стандартный вывод и ошибки раздельно, затем включите отладку. Это помогает не смешать найденный текст с диагностикой.
Быстрая ручная проверка строится в несколько шагов. Попробуйте найти короткое частое слово, включите --warn-empty, скопируйте фрагмент из просмотрщика и сравните с выводом pdftotext. Если текст извлекается, но символы искажены, проблема связана с картой шрифта или кодировкой. Если извлекается только часть страниц, документ может сочетать электронный текст и отсканированные приложения.
Нельзя определять наличие текстового слоя только по возможности выделить прямоугольник мышью. Некоторые просмотрщики распознают изображение самостоятельно или выделяют невидимый OCR-слой с ошибочной геометрией. Проверка командой показывает именно тот текст, который доступен Poppler и будет участвовать в сопоставлении. Для ответственного аудита добавьте в контрольный набор скан, обычный электронный PDF и смешанный документ.
Подготовка сканов перед поиском
Когда страницы состоят из изображений, перед pdfgrep нужен отдельный этап OCR, создающий текстовый слой. Практичная схема сохраняет исходный PDF, формирует распознанную копию и только затем запускает поиск. Это важнее преобразования в простой TXT: PDF с добавленным слоем сохраняет страницы, поэтому -n продолжает указывать на место в документе, а найденный фрагмент можно проверить визуально.
Язык распознавания должен соответствовать документу. Для смешанного русского и английского текста выбирают оба языковых набора; иначе латинские артикулы или кириллические фамилии будут искажаться. Низкое разрешение, перекос, тени у корешка, таблицы и печати повышают число ошибок. pdfgrep не оценивает уверенность OCR, поэтому совпадение может быть ложным, а отсутствие — следствием неверно распознанной буквы.
После OCR выполните контроль по словам разной сложности: частому слову, длинной фамилии, числовому идентификатору и фрагменту с пунктуацией. Для идентификаторов полезно разрешить типичные подмены, например букву О и ноль, но слишком свободный шаблон увеличит число ложных совпадений. В юридическом или финансовом процессе найденный номер нужно сверять с изображением страницы.
Не перезаписывайте подписанный оригинал или экземпляр длительного хранения. Добавление текстового слоя изменяет байты файла и обычно нарушает криптографическую подпись. Храните распознанную копию с явным суффиксом, а в отчёте связывайте её с исходным документом. Если политика запрещает изменение, распознавайте во временную рабочую область и удаляйте её после проверки с учётом требований к конфиденциальности.
После распознавания включение --unac иногда улучшает поиск слов с диакритикой и лигатурами, но оно не исправляет ошибочные буквы OCR и доступно не во всех сборках. Основная точность достигается качеством изображения и правильными языковыми моделями. pdfgrep применяется уже к сформированной последовательности символов и не знает, каким способом она была получена.
Логические условия И, ИЛИ и НЕ
Несколько -e и строки из файла -f работают как логическое ИЛИ: достаточно совпадения любого шаблона. Это подходит для списка синонимов, вариантов написания или нескольких кодов ошибок. Результат не доказывает, что в документе присутствуют все перечисленные выражения.
Условие И строится последовательной фильтрацией списка файлов. Первый проход с -l -Z выдаёт документы, содержащие фразу A, второй ищет фразу B только в полученном наборе. Нулевой разделитель сохраняет имена с пробелами, двоеточиями и переводами строк. Официальный пример использует именно такую схему для поиска PDF, где одновременно встречаются два слова.
pdfgrep -Z -l -F 'условие A' *.pdf |
xargs -0 pdfgrep -Hn -F 'условие B'
Пустой результат первого этапа требует внимания: некоторые реализации xargs без дополнительного параметра всё равно запускают вторую команду без файлов. В переносимом скрипте проверьте, как ведёт себя установленный xargs, или сохраните список и убедитесь, что он не пуст. Не подставляйте текущий каталог по умолчанию, если отсутствие кандидатов означает корректный нулевой результат.
Условие НЕ на уровне документов реализует -L: выводятся файлы, где шаблон не найден. Но непрочитанный PDF нельзя автоматически считать документом без совпадения. Сначала отделите ошибки и пустые сканы, затем формируйте отрицательный список. Для условия A, но не B получите набор с A и исключите из него файлы с B внешним сравнением списков.
Условие две фразы на одной странице требует пересечения пар имя файла — страница. Два обычных прохода с -Hn дают исходные пары, которые затем нормализуются и сравниваются. Поиск одной большой регулярной конструкцией ненадёжен, потому что фразы могут находиться на разных строках, а порядок извлечения не обязан повторять визуальный макет.
Формирование воспроизводимого отчёта
Читаемый терминальный вывод и стабильный машинный протокол имеют разные требования. Для отчёта явно включите имя файла и номер страницы, отключите цвет и зафиксируйте режим нумерации. Не полагайтесь на автоматические значения, терминальную ширину и пользовательский алиас. Команда должна одинаково работать из интерактивной оболочки, планировщика и CI.
LC_ALL=C.UTF-8 pdfgrep -Hn --color=never -F 'обязательная фраза' documents/*.pdf \
>report.txt 2>report-errors.txt
status=$?
Выбранная локаль влияет на обработку Unicode и регистр. Фиксация UTF-8 уменьшает различия между машинами, но конкретное имя локали может отличаться. Перед переносом скрипта проверьте доступные значения. Если шаблон и документы содержат только ASCII, нейтральная локаль может дать более предсказуемый результат, однако для кириллицы она непригодна.
Обычный двоеточечный формат удобен для просмотра, но не является универсальным CSV. Имя файла, метка страницы и текст способны содержать выбранный разделитель. -Z делает границу после имени однозначной, однако остальная строка всё ещё требует разбора с учётом выбранных полей. Для сложного экспорта безопаснее небольшой скрипт, который читает байты, экранирует значения и создаёт JSON или CSV библиотечными средствами.
К отчёту стоит добавлять команду без пароля, дату выполнения, список или контрольные суммы входных файлов, код завершения и отдельный журнал ошибок. Тогда повторная проверка объяснит, почему количество результатов изменилось: обновились документы, изменился шаблон, другая библиотека извлекла текст иначе или часть файлов не прочиталась.
Сортировка должна учитывать назначение. Лексикографическая сортировка строки может поставить страницу 10 раньше страницы 2. Для числового индекса извлеките поля и сортируйте страницу как число. Для меток страниц универсального порядка нет: римские числа, арабские номера и приложения требуют собственного правила. Оригинальный порядок вывода часто лучше сохраняет последовательность файлов и страниц.
При повторяемом аудите храните положительные и отрицательные контрольные примеры. Положительный файл должен содержать известное совпадение на известной странице; отрицательный — быть корректным текстовым PDF без фразы; третий — представлять скан без OCR. Такой набор проверяет шаблон, извлечение, обработку отсутствия совпадения и предупреждения о пустом тексте.
Измерение скорости и работа с кэшем
Время поиска состоит из открытия PDF, расшифровки объектов, извлечения текста и сопоставления шаблона. Для небольшого файла регулярное выражение почти не заметно, а для тысячи объёмных руководств основную стоимость создаёт повторный разбор страниц. Поэтому оптимизация начинается с измерения на реальной коллекции, а не с усложнения шаблона.
--cache сохраняет извлечённый текст в каталоге ${XDG_CACHE_HOME}/pdfgrep и ускоряет последующие запросы к большим неизменным файлам. Кэш полезен, когда по одной библиотеке выполняют разные поиски. Для одноразового прохода он добавляет запись на диск и может не дать выигрыша. Сравнивайте первый и повторный запуск отдельно.
Кэш ограничен: сохраняется не бесконечная история, а до двухсот записей старше суток. Это означает, что поведение на очень большой коллекции зависит от очередности и частоты обращений. Нельзя считать его заменой постоянному полнотекстовому индексу. Если ежедневно выполняются десятки запросов по сотням тысяч неизменных документов, индексирующая система обычно масштабируется лучше.
Для корректного теста очистите влияние файлового кэша операционной системы или хотя бы повторяйте измерение несколько раз и фиксируйте условия. Сравните поиск одного частого слова, редкого точного токена и сложного выражения. Отдельно измерьте проход с -l, полным выводом и большим контекстом: печать тысяч строк может стать более дорогой, чем само сопоставление.
Ограничение области часто эффективнее кэша. --page-range сокращает число страниц, --include — число файлов, -m 1 завершает обработку файла после первого совпадения, а -q прекращает весь вызов после первого успеха. Выбирайте их только тогда, когда сокращённый результат действительно отвечает на задачу.
Параллельная обработка ускоряет коллекцию независимых PDF на многоядерном процессоре. Она не ускоряет один файл и может ухудшить ситуацию на медленном диске, сетевом хранилище или при нехватке памяти. Начните с малого числа процессов, включите -H, отключите цвет и сортируйте объединённый вывод после завершения. Диагностику каждого процесса нужно сохранить, иначе ошибка потеряется среди строк.
Проверка качества результатов
Полнота поиска оценивается не количеством строк, а контрольной выборкой. Выберите документы, где фраза точно есть, где её точно нет и где она записана с альтернативным дефисом, регистром или переносом. Запустите простой буквальный запрос, затем варианты. Это показывает, какие расхождения вызваны шаблоном, а какие — извлечением текста.
Ложноположительные результаты обычно возникают у слишком коротких шаблонов, общих числовых форматов и альтернатив без границ. Уменьшить их помогают более длинный префикс, явные классы символов, проверка соседнего контекста и последующая валидация. Не пытайтесь устранить все ложные совпадения одним огромным выражением, если понятнее разделить поиск и проверку.
Ложноотрицательные результаты вызывают сканы, повреждённые карты символов, лигатуры, типографские знаки, переносы, OCR-ошибки и неверный диапазон страниц. Для каждого класса нужен собственный тест. Включение -i исправляет только различие регистра и не помогает против отсутствующего текстового слоя.
При обновлении Poppler повторяйте контрольный набор. Порядок и нормализация извлечённого текста могут измениться, особенно в сложных колонках и таблицах. Сравнивайте не только количество совпадений, но и пары файл — страница, коды завершения и список предупреждений.
Финальная проверка должна открывать часть результатов в просмотрщике. pdfgrep подтверждает наличие последовательности в текстовом слое, но не оценивает, виден ли текст, относится ли он к основной странице, аннотации или скрытому OCR-слою, и не проверяет юридический смысл. Для ответственных решений автоматический список остаётся инструментом отбора, а не единственным доказательством.
Сравнение pdfgrep с аналогами
| Программа | Лучше подходит для | Главное ограничение |
|---|---|---|
| pdfgrep | Быстрого поиска шаблонов в PDF из shell-скриптов без предварительного индекса | Не выполняет OCR и работает только с PDF |
| ripgrep-all | Единого поиска по PDF и многим другим форматам с адаптерами и кэшем | Зависит от внешних конвертеров для разных типов файлов |
| Recoll | Постоянной индексируемой коллекции с графическим поиском и полнотекстовой базой | Нужно заранее построить и обслуживать индекс |
| pdftotext + grep | Гибкого конвейера, когда требуется отдельно управлять извлечением и поиском | Нужно самостоятельно связывать строки с файлами и страницами |
| MuPDF mutool + grep | Сценариев, где уже используется набор MuPDF и нужен промежуточный текст | Нет единой команды с привычными PDF-специфичными ключами pdfgrep |
| PDF Commander | Ручного поиска внутри открытого PDF вместе с редактированием и работой через визуальные инструменты | Не заменяет рекурсивный shell-поиск по каталогу |
pdfgrep выбирают, когда нужен воспроизводимый запрос по одному файлу или каталогу и результат должен войти в shell-конвейер. ripgrep-all удобнее для смешанной коллекции форматов, Recoll — для многократного интерактивного поиска по постоянной коллекции, а связка pdftotext с grep даёт максимальный контроль над промежуточным текстом. PDF Commander лучше подходит пользователю, которому одновременно нужны визуальный поиск, исправление страниц и редактирование, но не массовая терминальная обработка.
Как выбрать параметры для конкретной задачи
Для точной известной фразы начните с -F. Для вариативного написания добавьте -i или несколько -e. Регулярное выражение выбирайте только тогда, когда нужно описать структуру: номер, диапазон символов, альтернативу или повторение. Чем проще шаблон, тем легче объяснить результат и найти ошибку.
Если важен документ, используйте -l; если страница — -n; если распространённость по страницам — -p; если число вхождений — -c; если только факт наличия — -q. Эти режимы отвечают на разные вопросы и не должны механически комбинироваться.
Для папки сначала примените -r и маски имён. Когда нужны условия по размеру, дате или пути, перейдите к find -print0. Для повторных запросов включите --cache. Для независимых файлов на многоядерной машине рассмотрите GNU Parallel, но измерьте нагрузку.
Для автоматизации явно задайте -H, --color=never и безопасные разделители. Сохраните код завершения и диагностический поток. Для интерактивного исследования, наоборот, полезны цвет, контекст и обычные двоеточия.
Проверочный рабочий процесс
- Убедитесь, что команда запускается и показывает справку.
- Возьмите один известный PDF и найдите короткое слово без регулярных выражений.
- Проверьте номера страниц через
-nи сравните с просмотрщиком. - Решите, нужен буквальный режим, POSIX-шаблон или PCRE2.
- Добавьте файлы или рекурсивный каталог, сохранив
-H. - Ограничьте маски, страницы и количество вывода.
- Для скрипта отключите цвет, используйте нулевые разделители и обработайте коды 0, 1 и 2.
- Если запросы повторяются, измерьте эффект
--cache. - Отдельно зарегистрируйте непрочитанные и сканированные документы.
- Проверьте итоговую выборку вручную на нескольких положительных и отрицательных примерах.
Такой порядок отделяет четыре независимых причины проблем: установку, извлечение текста, логику шаблона и файловый обход. Когда все параметры добавлены одновременно, ошибка в кавычках легко маскируется пустым сканом, а неверная маска — слишком строгим выражением. Последовательная проверка делает результат объяснимым.
Разбор нестандартных случаев
Нужно найти две фразы в одном документе
Первый вызов с -l формирует нулём разделённый список файлов с первой фразой, второй обрабатывает только их. Несколько -e не подходят, потому что означают любая из фраз.
Нужно найти фразу на одной и той же странице с другой фразой
Сам pdfgrep не строит логическое выражение на уровне страницы. Получите вывод с номерами страниц для каждого шаблона, нормализуйте пары файл — страница и пересеките списки внешней командой или небольшим скриптом.
Нужно исключить большие файлы
Используйте find с условием размера и -print0. Параметры --include и --exclude фильтруют имена, но не размер.
Нужно вывести только первое совпадение каждого файла
Добавьте -m 1 и -H. Если текст не нужен, быстрее и короче использовать -l.
Нужно найти все PDF без обязательного текста
Передайте набор файлов и включите -L -F. Ошибки чтения проверяйте отдельно; непрочитанный документ нельзя автоматически считать файлом без фразы.
Нужно сохранить результат для CSV
Не пытайтесь разделять произвольные имена двоеточием. Получите нулевые разделители или обработайте вывод программно. Текст совпадения может содержать запятые, кавычки и переводы строк после дальнейшей обработки, поэтому поля CSV должны корректно экранироваться.
Что контролировать в регулярной эксплуатации
После обновления Poppler повторите набор контрольных запросов: извлечение текста иногда меняется вместе с библиотекой. Храните несколько PDF с известными результатами, включая кириллицу, лигатуры, таблицы, пароль и пустой скан. Это быстрее ручного обнаружения расхождений в рабочей коллекции.
Скрипты должны фиксировать точную команду без секретов, набор входных файлов, время, код завершения и число ошибок. Не полагайтесь на текущий каталог и пользовательские алиасы. Используйте абсолютные пути там, где запуск выполняется из планировщика или CI.
Периодически проверяйте размер кэша и права на него. Если документы содержат персональные или коммерческие сведения, извлечённый текст требует такой же защиты, как оригиналы. На общей машине разумно задавать отдельный XDG_CACHE_HOME внутри защищённого рабочего каталога.
При росте коллекции сравните подход с индексирующей системой. Если время уходит на повторное открытие тысяч неизменных файлов, Recoll или другой индекс может оказаться рациональнее. pdfgrep остаётся сильным вариантом для прозрачных одноразовых запросов, скриптов и коллекций, где не хочется поддерживать отдельную базу.
Итоговый подход к работе
Наиболее надёжная схема строится от простого буквального запроса к точному автоматизированному конвейеру. Сначала подтверждают наличие текстового слоя, затем добавляют регистр, номера страниц и контекст, после чего расширяют область до каталога. Для отчётов включают имя файла, отключают цвет и обрабатывают коды завершения; для необычных имён используют нулевые разделители.
pdfgrep особенно полезен там, где результат должен быть повторяемым и проверяемым: в технических хранилищах, наборах договоров, научной библиотеке и сценариях контроля PDF. Его ограничения также предсказуемы: нет OCR, нет визуального редактирования, нет семантического поиска и нет универсального индекса для всех форматов. Если эти границы учтены заранее, команда решает поиск без лишних промежуточных файлов и легко встраивается в существующие инструменты оболочки.