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

335
Grigoris L.

У меня странная проблема с 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превращает все строки в одну строку, а второй создает команду bind), когда я запускаю

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

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

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

0
`grep` ожидает окончания строки (возможно, присутствует), а` darfst -0` ожидает NUL-байтов (вероятно, отсутствует) eckes 6 лет назад 0

2 ответа на вопрос

0
woolfie

Страница man для xargs гласит:

-Я заменяю-ул

 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).

Thnx! Как новичок, это тонкое различие (аргумент против аргументов) должно было быть точно определено для меня ... Момент новичка, ага ... Мое предыдущее понимание состояло в том, что xargs вызывал shell -или что-то для выполнения команды ... Очевидно, не так ... , Grigoris L. 6 лет назад 0
0
AFH

Есть несколько неправильных вещей и ненужная сложность:

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

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

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

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

Спасибо за подробный ответ и за выявление всех ошибок. Есть некоторые сомнения по поводу замечания № 3, поскольку exiftool также печатает две строки, отличные от имен файлов, которые должны быть выброшены. Grigoris L. 6 лет назад 0
@GrigorisL. - Все, что я могу сказать, это то, что команда отлично работает для меня, а команда `exiftool`, которую я цитировал, выдает только одну строку с именем файла. Для справки, моя версия exiftool 10.10, и я использую Ubuntu 16.04. AFH 6 лет назад 0
@ ΑFH В конце концов, ты совершенно прав. Когда из bash вызывается -p $ FileName, он печатает только имена файлов. Когда он вызывается из файла параметров, как я это делал изначально, вывод более озадачен. Grigoris L. 6 лет назад 0
Хорошо, но я поместил `$ ` в качестве единственной строки в файле (без комментариев, заголовков и т. Д.), И это сработало одинаково хорошо. Я использовал встроенную строку для тестирования, и, поскольку мой конечный формат был настолько прост, казалось, что нет смысла помещать его в отдельный файл. Кстати, `{}` в этом случае необязательны: более простой `$ FileName` эквивалентен. AFH 6 лет назад 0

Похожие вопросы