Подтвердить что ты не робот

Понимание команды UNIX xargs

Я очень смущен этим. Нужны некоторые пояснения.

Пример 1:

pgrep string | xargs ps

Пример 2:

find . | xargs grep whatever

Из примера 1 я собираю его следующим образом:

Найдите строку, которая является частью имени запущенного процесса и возвращает идентификаторы процессов всех совпадений в "xargs ps" → , которые просто присоединяют ps к совпадениям (которые сами являются самими процессами) получить тот же результат, что и:

ps <processid>

Может кто-нибудь объяснить, что действительно делает xargs в этом случае?

Из примера 2 я собираю его следующим образом:

Это, чтобы найти некоторую "строку" рекурсивно из текущего рабочего каталога. Здесь, как работает "xargs"?

Я считал, что "xargs" повторно добавляет данные со стандартного ввода в "аргумент", заданный для xargs (который обычно является командой UNIX сам по себе).

Из справочной страницы xargs():

xargs считывает элементы со стандартного ввода, разделенные пробелами (которые могут быть защищенные двойными или одинарными кавычками или обратная косая черта) или новые строки и выполняет команду (по умолчанию -/bin/echo) один или несколько раз с любым начальные аргументы, за которыми следуют элементы, считанные со стандартного ввода. Пустые строки на стандартном входе игнорируются.

4b9b3361

Ответ 1

В общем, xargs используется так

prog | xargs utility

где prog ожидаются к выходу одного или более новая строка/разделенному пробел результаты. Хитрость в том, что xargs не обязательно вызывает utility один раз для каждого результата, вместо этого он разбивает результаты на подсписки и вызывает utility для каждого подсписка. Если вы хотите заставить xargs вызывать utility для каждого результата, вам нужно будет вызвать ее с помощью xargs -L1.

Обратите внимание, что xargs обещает вам, что Подсписок отправляется utility короче ARG_MAX (Если вам интересно, вы можете получить текущее значение ARG_MAX с помощью getconf ARG_MAX.) Это, как он избегает тех страшных "список аргументов для длинных" ошибок.

Ответ 2

Хорошим примером того, что делает xargs, является попытка получить отсортированные контрольные суммы для каждого файла в каталоге с помощью find.

find . | cksum  | sort

возвращает только одну контрольную сумму, и это не понятно, для чего это контрольная сумма. Не то, что мы хотим. Труба отправляет stdout из find в stdin для cksum. То, что действительно хочет cksum, это список аргументов командной строки, например

cksum file001.blah file002.blah  file003.blah

будет сообщать три строки, по одному на файл, с требуемыми контрольными суммами. Xargs делает магический трюк - преобразование stdout предыдущей программы во временную и скрытую командную строку для подачи следующего. Командная строка, которая работает:

find . | xargs cksum | sort

Обратите внимание на отсутствие связи между xargs и cksum.

Ответ 3

$ echo 'line1
> line2
> line3
> ...
> lineN ' | xargs cmd1 -a -b

приведет к:

$ cmd1 -a -b line1 line2 line3 ... lineN

xargs разбивает cmd1 ... на несколько выполнений cmd1, если количество строк становится слишком большим.

xargs может использоваться для многих других задач, связанных с передачей строк stdin в качестве позиционных аргументов. Взгляните на параметр капитала -P в xargs (1) для одновременного запуска нескольких экземпляров команды.

Ответ 4

xargs обычно используется для группировки аргументов вместе, так что вы не получаете ошибку "слишком много аргументов", которая возникает, когда вы передаете большое количество аргументов команде

Ответ 5

#!/bin/sh
#script to echo out the arguments 1 at a time!
for a in $*
do
    echo $a
done

команда

$sh myscript 1 2 3 4 5

даст

1
2
3
4
5

но

$sh myscript 1 2 3 4 5 6 7 8 9 10 11

не будет работать, поскольку максимальное количество параметров будет превышено (im действительно не уверен, что такое max, но позволяет сказать его 10 для этого примера!)

Чтобы обойти это, мы могли бы использовать

#!/bin/sh
#script to echo out the arguments 1 at a time!
for a in $*
do
    echo $a | xargs echo
done

мы могли бы запустить его следующим образом

 $sh myscript "1 2 3 4 5" "6 7 8 9 10 11"

и получить правильный результат, так как есть только 2 параметра