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

Я в значительной степени запутался в этом. Нужны некоторые разъяснения.

Пример 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) один или несколько раз с любым initial-аргументы, за которыми следуют элементы, считываемые из стандартного ввода. Пустая строка на стандартном входе игнорируются.

5 ответов


В общем xargs используется следующим образом

утилита prog | xargs

здесь prog ожидается, что выход один или более строки/пробел результаты. Фокус в том, что xargs не! нессарлы зов утилиты один раз для каждого результата, вместо этого разбивает список результатов на подсписки и вызывает утилиты для каждого подсписка. Если вы хотите заставить xargs позвонить утилиты для каждого результата вам нужно будет вызывать его с команды xargs -Л1.

отметим, что xargs обещает вам, что подсписок отправлено утилиты меньше, чем ARG_MAX (вот как он избегает этих страшных список аргументов для long ошибки). Вы можете получить текущее значение ARG_MAX используя getconf ARG_MAX


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

find . | cksum  | sort

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

cksum file001.blah file002.blah  file003.blah

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

find . | xargs cksum | sort

Примечание нет трубы между xargs и cksum.


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

в результате:

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

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

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


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


#!/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

не будет работать, так как максимальное количество параметров превышено (я не уверен, что Макс, но давайте скажем его 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 параметра