Невозможно заставить работать конструкцию xargs

Невозможно заставить работать конструкцию xargs

У меня странная проблема сxargs.
У меня естьxargsконструкция, которая не работает, хотя когда я повторяю команду, она работает отлично. Мой однострочный вариант следующий:

 exiftool -p exifprintformat  -if '$Subject =~/DATA/i' -q  *.pdf |grep pdf |sed 's/ //g'|xargs|xargs -0 -I % pdftk % cat output binder1.pdf  

и выход

Ошибка: Невозможно найти файл. Ошибка: Не удалось открыть файл PDF: 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf

  • Выбирает exiftoolвсе PDF-файлы, содержащие слово DATA в теге темы,
  • Инструкция -p exifprintformatпо exiftoolпечати только имени файла,
  • Выбирает grepтолько строки с pdf,
  • Удаляет sedпробелы,
  • Первый xargобъединяет все строки в одну, а второй создает команду привязки). Когда я запускаю

exiftool -p exifprintformat -if '$Subject =~/DATA/i' -q *.pdf |grep pdf |sed 's/ //g'|xargs|xargs -I{} echo pdftk {} cat output binder1.pdf

я получил

pdftk 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf cat output binder1.pdf

который работает отлично.

Очевидно, я делаю что-то не так... Но что?

решение1

Есть несколько ошибок и ненужных сложностей:

  1. Двойной xargsвызов означает, что второй видит одну строку входных данных, поэтому {}заменяется только один раз одной строкой, содержащей все совпадающие имена файлов, но echoне показывает эту разницу в выходных данных (сравните echo a bс echo "a b").
  2. Аргумент -0означает, что между входными аргументами xargsдолжен быть нулевой '\0'символ ( ), но их нет; это также заставляет входные данные обрабатываться как один параметр.
  3. Выводя только имя файла при выполнении условия, вы получаете по одному имени файла на строку, к которому можно напрямую обратиться xargsбез необходимости использования grepили sed.
  4. К сожалению, xargs -Iв каждой строке ввода задается одна команда, и нет возможности добавлять конечные параметры, но есть простой обходной путь: добавьте конечные параметры в поток ввода.

Это упрощенная команда с добавленными конечными параметрами (я тестировал с другим -ifусловием, не имея ни одного подходящего PDF-файла):

{ exiftool -p '${FileName}' -if '$Subject =~/DATA/i' -q *.pdf; \
  echo -e "cat\noutput\nbinder1.pdf"; } | xargs -d'\n' pdftk

Эта xargs -d'\n'опция позволяет команде работать, когда имена файлов содержат пробелы.

решение2

На странице руководства по xargs написано:

-Я заменяю-str

  Replace occurrences of replace-str in the initial-arguments with
  names read from standard input.   Also, unquoted blanks do not
  terminate input items; instead the separator is the newline
  character.  Implies -x and -L 1.

Другими словами, в итоге у вас остается один аргумент под названием " 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf"

Я предлагаю вообще отказаться от xargs и изменить порядок команд примерно так:

pdftk $(exiftool -p exifprintformat -if '$Subject =~/DATA/i' -q *.pdf |grep pdf |sed 's/ //g'| tr '\n' ' ') cat output binder1.pdf

Все это предполагает, что в именах файлов нет пробелов (безопасное предположение, поскольку вы в любом случае удаляли все пробелы с помощью sed).

Связанный контент