xargs
Разработчик(и) | Различные с открытым исходным кодом и коммерческие разработчики разработчики |
---|---|
Операционная система | Unix , Unix-подобные , Plan 9 , IBM i |
Платформа | Кросс-платформенный |
Тип | Команда |
xargs сокращение расширенные аргументы « » от ( [1] ) — это команда в Unix и большинстве Unix-подобных операционных систем, используемая для создания и выполнения команд из стандартного ввода . Он преобразует входные данные стандартного ввода в аргументы команды.
Некоторые команды, такие как grep
и awk
может принимать входные данные либо в виде аргументов командной строки, либо из стандартного ввода. Однако другие, такие как cp
и echo
может принимать входные данные только в качестве аргументов, поэтому xargs необходим .
Порт более старой версии GNU. xargs доступен для Microsoft Windows как часть UnxUtils коллекции , состоящей из собственных Win32- портов распространенных GNU Unix-подобных утилит. [2] Переписывание с нуля под названием wargs является частью TextTools с открытым исходным кодом. [3] проект. Команда xargs также была перенесена в операционную систему IBM i . [4]
Примеры
[ редактировать ]Одним из вариантов использования команды xargs является удаление списка файлов с помощью команды rm . Системы POSIX имеют ARG_MAX для максимальной общей длины командной строки, [5] [6] поэтому команда может завершиться неудачно с сообщением об ошибке «Список аргументов слишком длинный» (это означает, что предел системного вызова exec на длину командной строки был превышен): rm /path/*
или rm $(find /path -type f)
. (Последний вызов неверен, так как он может расширить globs в выходных данных.)
Это можно переписать с помощью xargs
команда, чтобы разбить список аргументов на подсписки, достаточно маленькие, чтобы их можно было принять:
$ find /path -type f -print | xargs rm
В приведенном выше примере find
Утилита подает входные данные xargs
с длинным списком имен файлов. xargs
затем разбивает этот список на подсписки и вызывает rm
один раз для каждого подсписка.
Некоторые реализации xargs также можно использовать для распараллеливания операций с -P maxprocs
аргумент, чтобы указать, сколько параллельных процессов следует использовать для выполнения команд над списками входных аргументов. Однако выходные потоки могут быть не синхронизированы. Это можно преодолеть, используя --output file
аргумент, где это возможно, а затем объединение результатов после обработки. В следующем примере 24 процесса ставятся в очередь и ждут завершения каждого, прежде чем запускать другой.
$ find /path -name '*.foo' | xargs -P 24 -I '{}' /cpu/bound/process '{}' -o '{}'.out
xargs часто охватывает ту же функциональность, что и функция подстановки команд во многих оболочках , обозначаемая обратными кавычками ( `...`
или $(...)
). xargs также является хорошим помощником для команд, выводящих длинные списки файлов, таких как find
, locate
и grep
, но только если использовать -0
(или эквивалентно --null
), с xargs
без -0
плохо обрабатывает имена файлов, содержащие '
, "
и космос. GNU Parallel — аналогичный инструмент, который обеспечивает лучшую совместимость с find , locate и grep, когда имена файлов могут содержать '
, "
и пробел (новая строка по-прежнему требует -0
).
Размещение аргументов
[ редактировать ]-I
вариант: один аргумент
[ редактировать ] Команда xargs предлагает опции для вставки перечисленных аргументов в какую-либо позицию, отличную от конца командной строки. -I
Опция xargs принимает строку, которая будет заменена предоставленным вводом перед выполнением команды. Общий выбор – это %
.
$ mkdir ~/backups
$ find /path -type f -name '*~' -print0 | xargs -0 -I % cp -a % ~/backups
Заменяемая строка может появляться в командной части несколько раз. С использованием -I
вообще ограничивает количество используемых каждый раз строк до одной.
Трюк с ракушкой: любое число
[ редактировать ]Другой способ добиться аналогичного эффекта — использовать оболочку в качестве запускаемой команды и разобраться со сложностью в этой оболочке, например:
$ mkdir ~/backups
$ find /path -type f -name '*~' -print0 | xargs -0 sh -c 'for filename; do cp -a "$filename" ~/backups; done' sh
Слово sh
в конце строки — оболочка POSIX. sh -c
заполнить для $0
, часть позиционных параметров «имя исполняемого файла» (argv). Если бы его не было, имя первого совпадающего файла было бы присвоено $0
и файл не будет скопирован в ~/backups
. Для заполнения этого пробела можно также использовать любое другое слово. my-xargs-script
например.
С cp
принимает несколько файлов одновременно, можно также просто сделать следующее:
$ find /path -type f -name '*~' -print0 | xargs -0 sh -c 'if [ $# -gt 0 ]; then cp -a "$@" ~/backup; fi' sh
Этот скрипт запускается cp
со всеми переданными ему файлами при передаче каких-либо аргументов. Это более эффективно, поскольку только один вызов cp
выполняется для каждого вызова sh
.
Проблема сепаратора
[ редактировать ]Многие утилиты Unix ориентированы на строки. Они могут работать с xargs
пока строки не содержат '
, "
, или пробел. Некоторые утилиты Unix могут использовать NUL в качестве разделителя записей (например, Perl (требуется -0
и \0
вместо \n
), locate
(требуется использование -0
), find
(требуется использование -print0
), grep
(требует -z
или -Z
), sort
(требуется использование -z
)). С использованием -0
для xargs
решает эту проблему, но многие утилиты Unix не могут использовать NUL в качестве разделителя (например, head
, tail
, ls
, echo
, sed
, tar -v
, wc
, which
).
Но часто люди забывают об этом и полагают, что xargs
также линейно-ориентирован, что не так (по умолчанию xargs
разделяется на символы новой строки и пробелы внутри строк, подстроки с пробелами должны быть заключены в одинарные или двойные кавычки).
Проблема сепаратора проиллюстрирована здесь:
# Make some targets to practice on
touch important_file
touch 'not important_file'
mkdir -p '12" records'
find . -name not\* | tail -1 | xargs rm
find \! -name . -type d | tail -1 | xargs rmdir
Выполнение вышеуказанного приведет к important_file
будет удален, но не удалит ни каталог с именем 12" records
, ни файл с именем not important_file
.
Правильное решение — использовать специфичный для GNU -print0
вариант, но tail
(и другие инструменты) не поддерживают строки, завершающиеся NUL:
# use the same preparation commands as above
find . -name not\* -print0 | xargs -0 rm
find \! -name . -type d -print0 | xargs -0 rmdir
При использовании -print0
вариант, записи разделяются нулевым символом вместо конца строки. Это эквивалентно более подробной команде: find . -name not\* | tr \\n \\0 | xargs -0 rm
или короче, переключая xargs
в (не POSIX) строчно-ориентированный режим с -d
(разделитель) вариант: find . -name not\* | xargs -d '\n' rm
но в целом использую -0
с -print0
следует отдавать предпочтение, поскольку переводы строк в именах файлов по-прежнему являются проблемой.
ГНУ parallel
является альтернативой xargs
который предназначен для тех же возможностей, но ориентирован на линии. Таким образом, используя вместо этого GNU Parallel, вышеописанное будет работать так, как ожидалось. [7]
Для сред Unix, где xargs
не поддерживает -0
ни -d
(например, Solaris, AIX), стандарт POSIX утверждает, что можно просто экранировать каждый символ обратной косой чертой: find . -name not\* | sed 's/\(.\)/\\\1/g' | xargs rm
. [8] В качестве альтернативы можно вообще избежать использования xargs, либо используя GNU Parallel, либо используя -exec ... +
функциональность find
.
Работа с подмножеством аргументов одновременно
[ редактировать ]Можно иметь дело с командами, которые могут принимать только один или два аргумента одновременно. Например, diff
Команда работает с двумя файлами одновременно. -n
возможность xargs
указывает, сколько аргументов одновременно следует передать данной команде. Команда будет вызываться повторно, пока все входные данные не будут исчерпаны. Обратите внимание, что при последнем вызове можно получить меньше аргументов, чем желаемое, если входных данных недостаточно. Использовать xargs
чтобы разбить ввод на два аргумента в каждой строке:
$ echo {0..9} | xargs -n 2
0 1
2 3
4 5
6 7
8 9
Помимо запуска на основе заданного количества аргументов одновременно, можно также вызывать команду для каждой строки ввода с помощью -L 1
вариант. Одновременно можно использовать произвольное количество строк, но чаще всего используется одна. Вот как можно diff
каждый git коммит против своего родителя. [9]
$ git log --format="%H %P" | xargs -L 1 git diff
Проблема с кодировкой
[ редактировать ]Обработка разделителя аргументов xargs
это не единственная проблема с использованием xargs
программа в режиме по умолчанию. Большинство инструментов Unix, которые часто используются для управления именами файлов (например, sed
, basename
, sort
и т. д.) являются инструментами обработки текста. Однако имена путей Unix на самом деле не являются текстом. Рассмотрим путь /aaa/bbb/ccc. Каталог /aaa и его подкаталог bbb обычно могут создаваться разными пользователями в разных средах. Это означает, что у этих пользователей могут быть разные настройки локали, а это означает, что aaa и bbb даже не обязательно должны иметь одинаковую кодировку символов. Например, aaa может быть в UTF-8, а bbb — в Shift JIS. В результате имя абсолютного пути в системе Unix может быть неправильно обработано как текст в односимвольной кодировке. Инструменты, которые полагаются на текстовые входные данные, могут не работать с такими строками.
Одним из способов решения этой проблемы является запуск таких инструментов в локали C, которая по существу обрабатывает байты ввода как есть. Однако это изменит поведение инструментов так, как пользователь может не ожидать (например, некоторые ожидания пользователя относительно поведения свертывания регистра могут не оправдаться).
Ссылки
[ редактировать ]- ^ «Список сокращений Unix: Полный список» . www.roesler-ac.de . Проверено 12 апреля 2020 г.
- ^ «Собственные порты Win32 некоторых утилит GNU» . unxutils.sourceforge.net .
- ^ «Средства обработки текста для Windows» .
- ^ ИБМ . «Программирование Qshell в IBM System i версии 7.2» (PDF) . Проверено 05 сентября 2020 г.
- ^ «Часто задаваемые вопросы по основным утилитам GNU» . Проверено 7 декабря 2015 г.
- ^ «Максимальная длина аргументов для нового процесса» . www.in-ulm.de .
- ^ Различия между xargs и GNU Parallel . GNU.org . По состоянию на февраль 2012 г.
- ^ Единая спецификация UNIX , версия 4 от Open Group. – Справочник по оболочке и утилитам,
- ^ Космин Стеджеран. «Вещи, которые вы (вероятно) не знали о xargs» . Проверено 7 декабря 2015 г.
Внешние ссылки
[ редактировать ]
- Единая спецификация UNIX , версия 4 от The Open Group : создание списков аргументов и вызов утилиты — Справочник по командной строке и утилитам,
Страницы руководства
[ редактировать ]- GNU Findutils Справочник -
- FreeBSD по основным командам Руководство : создать список(ы) аргументов и выполнить утилиту –
- NetBSD по основным командам Руководство : создать список аргументов и выполнить утилиту –
- OpenBSD по основным командам Руководство : создать список аргументов и выполнить утилиту –
- Solaris 11.4 по пользовательским командам Справочное руководство : создание списков аргументов и вызов утилиты –