как связать xargs с конвертером pdftotext для поиска в нескольких файлах PDF

Я делаю скрипт, который должен искать во всех файлах PDF в каталоге. Я нашел один преобразованный файл с именем «pdftotext», который позволяет мне использовать grep для файлов pef, но я могу запустить его только с одним файлом. Когда я хочу запустить его по всем файлам, присутствующим в каталоге, он терпит неудачу. Какие-либо предложения ?

Это работает: для одного файла

pdftotext my_file.pdf - | grep 'hot'

Это не удается: для поиска файлов PDF и преобразования в текст и поиска

SHELL PROMPT>find ~/.personal/tips -type f -iname "*" | grep -i "*.pdf" | xargs pdftotext |grep admin
pdftotext version 3.00
Copyright 1996-2004 Glyph & Cog, LLC
Usage: pdftotext [options] <PDF-file> [<text-file>]
  -f <int>          : first page to convert
  -l <int>          : last page to convert
  -layout           : maintain original physical layout
  -raw              : keep strings in content stream order
  -htmlmeta         : generate a simple HTML file, including the meta information
  -enc <string>     : output text encoding name
  -eol <string>     : output end-of-line convention (unix, dos, or mac)
  -nopgbrk          : don't insert page breaks between pages
  -opw <string>     : owner password (for encrypted files)
  -upw <string>     : user password (for encrypted files)
  -q                : don't print any messages or errors
  -cfg <string>     : configuration file to use in place of .xpdfrc
  -v                : print copyright and version info
  -h                : print usage information
  -help             : print usage information
  --help            : print usage information
  -?                : print usage information
SHELL PROMPT 139>

person Community    schedule 24.03.2015    source источник


Ответы (2)


xargs не подходит для этой работы: find делает все, что вам нужно, встроенно.

find ~/.personal/tips \
    -type f \
    -iname "*.pdf" \
    -exec pdftotext '{}' - ';' \
  | grep hot

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

find ~/.personal/tips \
    -type f \
    -iname "*.pdf" \
    -print0 \
  | xargs -0 -J % -n 1 pdftotext % - \
  | grep hot

Обратите внимание, что:

  • Команда find использует -print0 для NUL-разделения своего вывода.
  • Команда xargs использует -0 для разделения ввода NUL (что также отключает некоторое поведение, которое может привести к неправильной обработке имен файлов с пробелами в именах, литеральными кавычками и т. д.).
  • Команда xargs использует -n 1 для вызова pdftotext один раз для каждого файла.
  • Команда xargs использует -J % для указания сигила, где должна произойти замена, и соответствующим образом использует этот % в командной строке pdftotext.
person Charles Duffy    schedule 24.03.2015

find . -name '*.pdf' -print0 | xargs -0 -n1 -I '{}' pdftotext '{}' -

По умолчанию xargs попытается уместить как можно больше строк в командной строке для pdftotext. Вы не хотите этого. То, что вам нужно, это один файл на вызов, за которым следует «-». Этого можно добиться с помощью -n1 (ограничение одним аргументом на вызов) и -I '{}' (сделать {} заполнителем для того места, где аргумент будет соответствовать).

Параметр -print0 для поиска в сочетании с параметрами -0 для xargs заставляет использовать '\0' (пустые байты) вместо новой строки ('\n') в качестве разделителей аргументов.

Xargs с -n1 и -I{}, используемые таким образом, в значительной степени семантически эквивалентны find -exec, как рекомендовал Чарльз Даффи. Преимущество Xargs в том, что он может использовать многоядерные процессоры (он может запускать несколько экземпляров pdftotext одновременно; вы можете настроить их количество с помощью переключателя -P).

person PSkocik    schedule 24.03.2015
comment
Я получаю сообщение об ошибке SHELL PROMPT›find ~/.personal/tips/pdf -name '*.pdf' -print0 | xargs -0 -n1 -I{} pdftotext {} - xargs: {}: нет такого файла или каталога - person ; 24.03.2015
comment
Возможно, стоит процитировать {} на случай, если кто-то, кто читает этот ответ, использует zsh. (Вот почему я придерживаюсь %, предложенного на справочной странице xargs; я сам не использую zsh, но нет причин создавать режим отказа для других людей, использующих основную оболочку). - person Charles Duffy; 24.03.2015
comment
Кстати, в то время как вывод find может точно представлять все имена файлов, кроме тех, которые содержат символы новой строки, без использования -print0, поведение по умолчанию, используемое xargs для чтения содержимого, не так надежно без -0; он пытается интерпретировать кавычки, анализировать пробелы и т.п.; это не прямой эквивалент с обменом символами новой строки и NULL. Использование расширения GNU xargs -d $'\n' разумно, если xargs используется для чтения имен файлов, разделенных новой строкой, поскольку это отключает другие варианты поведения. - person Charles Duffy; 24.03.2015
comment
@Чарльз Даффи Приятно знать. Я придерживался -print0 (найти) + -0 в основном (xargs), пытаясь избежать темных углов обработки командной строки UNIX. - person PSkocik; 24.03.2015