Команда xargs: использование, опции -n и -I и работа с find
Команда xargs — это инструмент Linux, который превращает строки и слова со стандартного ввода в аргументы другой команды и запускает её. Когда мы в рабочей папке на сервере AlmaLinux 9 передали через xargs команде wc три файла журнала, найденные find, файл с пробелом в имени разбился на две части и возникла ошибка, а с -print0 и -0 появились количества строк всех трёх файлов.
Вывод ниже получен в рабочей папке под учётной записью root на сервере AlmaLinux 9.8. Список имён, журналы и временные файлы — это примеры, созданные для теста, а IP-адреса и пути папок в них тоже примерные значения.
1️⃣ Основы команды xargs
xargs делит стандартный ввод от предыдущей команды по пробелам и переводам строки и запускает команду, указанную после него, с этими частями в качестве аргументов. Мы проверили это на файле names.txt с одним именем в строке.
cat names.txtalice
bob
carol
dave
erinЕсли передать вывод cat в xargs echo, пять строк станут аргументами одного echo и выведутся одной строкой.
cat names.txt | xargs echoalice bob carol dave erinЕсли не указать команду после него, xargs запустит echo, поэтому результат тот же.
cat names.txt | xargsalice bob carol dave erinКанал соединяет вывод предыдущей команды со стандартным вводом следующей, поэтому в аргументы следующей команды ничего не попадает. Если передать list.txt с тремя именами файлов в wc -l только через канал, wc посчитает 3 строки самого списка.
cat list.txtlogs/access.log
logs/error.log
tmp/keep.txtcat list.txt | wc -l3Если поставить между ними xargs, три имени из списка станут аргументами wc и появится число строк для каждого файла.
cat list.txt | xargs wc -l 3 logs/access.log
2 logs/error.log
1 tmp/keep.txt
6 total2️⃣ Опции xargs -n и -I
Без опций весь ввод попадает в один запуск команды, поэтому чтобы повторять её, задайте через -n, сколько аргументов передавать за раз. На рисунке ниже видно, как те же пять имён группируются в зависимости от опции.
-n 1 запускает echo для каждого имени, и выводится пять строк.
cat names.txt | xargs -n 1 echoalice
bob
carol
dave
erin-n 2 группирует по два, а оставшееся передаёт отдельно.
cat names.txt | xargs -n 2 echoalice bob
carol dave
erinЧтобы увидеть запускаемые команды, добавьте -t. Сначала выводится строка команды, а под ней её вывод.
cat names.txt | xargs -t -n 2 echoecho alice bob
alice bob
echo carol dave
carol dave
echo erin
erinЕсли аргумент должен стоять не в конце команды, задайте заполнитель через -I. Вместо {} подставляется по одной строке, а если тот же текст встречается несколько раз, заменяются все вхождения.
cat names.txt | xargs -I {} echo 'user: {}'user: alice
user: bob
user: carol
user: dave
user: erincat names.txt | xargs -I {} echo '{} -> home/{}'alice -> home/alice
bob -> home/bob
carol -> home/carol
dave -> home/dave
erin -> home/erinТем же способом можно создать папку для каждого имени. Сначала создайте папку home, а затем через -I {} создайте в ней папки по именам: появится пять папок.
mkdir homecat names.txt | xargs -I {} mkdir home/{}ls homealice bob carol dave erin-I считает одну строку одним аргументом, поэтому её нельзя использовать вместе с -n. Когда мы указали обе, -I была проигнорирована с предупреждением, а {} вывелось как текст.
cat names.txt | xargs -I {} -n 2 echo {}xargs: warning: options --replace and --max-args/-n are mutually exclusive, ignoring previous --replace value
{} alice bob
{} carol dave
{} erin-L группирует по числу строк. Если в строке несколько слов, они передаются вместе, а в names.txt с одним именем в строке -L 2 дал тот же результат, что и -n 2.
cat names.txt | xargs -L 2 echoalice bob
carol dave
erin3️⃣ Связка find и xargs
Список имён не нужно создавать вручную: найденные find файлы можно сразу передать в xargs. Поиск файлов на .log в папке журналов находит три файла, и в имени одного из них есть пробел.
find /root/work/logs -name '*.log'/root/work/logs/access.log
/root/work/logs/error.log
/root/work/logs/old access.logКогда этот список передали как есть в xargs wc -l, имя с пробелом разбилось на old и access.log, появились две строки ошибок, а итог составил всего 5 строк по двум файлам.
find /root/work/logs -name '*.log' | xargs wc -l 3 /root/work/logs/access.log
2 /root/work/logs/error.log
wc: /root/work/logs/old: No such file or directory
wc: access.log: No such file or directory
5 total-print0 в find разделяет имена нулевым символом вместо перевода строки, а -0 в xargs делит аргументы только по этому нулевому символу. Вместе они выводят число строк всех трёх файлов, включая файл с пробелом.
find /root/work/logs -name '*.log' -print0 | xargs -0 wc -l 3 /root/work/logs/access.log
2 /root/work/logs/error.log
1 /root/work/logs/old access.log
6 totalОпция -exec в find делает то же самое. С + после {} найденные файлы передаются за один раз, поэтому результат тот же, а пробелы в именах find передаёт как есть. xargs принимает вывод и других команд, поэтому используйте его, когда ввод идёт не только от find, либо когда нужно задать число элементов за раз (-n) или число одновременных запусков (-P).
find /root/work/logs -name '*.log' -exec wc -l {} + 3 /root/work/logs/access.log
2 /root/work/logs/error.log
1 /root/work/logs/old access.log
6 totalЧтобы выбрать из найденных только файлы с нужной строкой, добавьте после xargs grep -l. wp-login оказался в двух файлах: журнале доступа и журнале ошибок.
find /root/work/logs -name '*.log' -print0 | xargs -0 grep -l wp-login/root/work/logs/access.log
/root/work/logs/error.log4️⃣ Удаление файлов командой xargs
Если поставить rm после xargs, найденные файлы удалятся за один раз, поэтому перед удалением проверьте, какие файлы будут переданы. Если поставить echo перед rm, выведется только строка команды, которая запустилась бы, а файлы останутся на месте.
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 echo rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmpls tmpcache-a.tmp cache-b.tmp cache-c.tmp keep.txtС -p xargs спрашивает о каждой команде, запускать ли её. Если ввести n, ничего не удаляется и три временных файла остаются.
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...nls tmpcache-a.tmp cache-b.tmp cache-c.tmp keep.txtЕсли ввести y, три файла удаляются и остаётся только keep.txt.
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...yls tmpkeep.txtЕсли ввод пуст, xargs один раз запускает команду без аргументов. При передаче пустого файла rm запускается без аргументов и выдаёт ошибку [rm: missing operand]; с -r команда вообще не запускается.
cat empty.txt | xargs rmrm: missing operand
Try 'rm --help' for more information.cat empty.txt | xargs -r rm5️⃣ Параллельный запуск, разделители и опции xargs
🔲 Параллельный запуск и разделители
Когда команды идут по одной, при большом числе целей время растёт. -P задаёт число одновременно запускаемых команд. Четыре sleep по 1, 2, 3 и 4 секунды заняли 10 секунд подряд и завершились за самые долгие 4 секунды при одновременном запуске с -P 4.
time seq 1 4 | xargs -n 1 sleep
real 0m10.007s
user 0m0.004s
sys 0m0.003stime seq 1 4 | xargs -n 1 -P 4 sleep
real 0m4.005s
user 0m0.001s
sys 0m0.006sЕсли ввод разделён символом, отличным от перевода строки или пробела, задайте разделитель через -d. При разбиении через -d , трёх имён, соединённых запятыми, каждое имя выводится отдельной строкой.
printf 'alice,bob,carol' | xargs -d , -n 1 echoalice
bob
carolЧтобы читать из файла вместо стандартного ввода, укажите имя файла в -a. Пять имён из names.txt ушли в echo без канала.
xargs -a names.txt echoalice bob carol dave erin🔲 Опции команды xargs
📌 Основные опции: результаты из этой статьи
| Опция | Назначение | Результат в этой статье | |
|---|---|---|---|
| -n | Задаёт число аргументов на один запуск команды | Пять имён группируются по два через -n 2, а echo запускается три раза | |
| -I | Подставляет по одной строке в заполнитель и запускает для каждой строки | Вместо {} подставляется имя; вместе с -n опция -I игнорируется с предупреждением | |
| -L | Задаёт число строк на один запуск команды | В файле с одним именем в строке результат как у -n 2 | |
| -t | Сначала выводит строку запускаемой команды | Строка команды появляется раньше вывода | |
| -0 | Делит ввод только по нулевому символу (вместе с find -print0) | Без неё имена с пробелами разбиваются и появляются две строки ошибок; с ней у всех трёх файлов по 6 строк | |
| -p | Спрашивает о каждой команде, запускать ли её | При n файлы остаются, при y три файла удаляются | |
| -r | Не запускает команду при пустом вводе | Без неё [rm: missing operand], с ней запуска нет | |
| -P | Задаёт число одновременно запускаемых команд | Четыре sleep: подряд 10 секунд, с -P 4 всего 4 секунды | |
| -d | Задаёт разделитель для деления ввода | -d , даёт по одной строке на имя | |
| -a | Читает ввод из файла вместо стандартного ввода | Пять имён из names.txt уходят в один echo |
📎 Другие опции: по официальному руководству
| Опция | Назначение | |
|---|---|---|
| -s | Задаёт максимальное число символов в строке команды | |
| -x | При превышении размера -s завершается без запуска | |
| -E | Прекращает чтение ввода на строке, содержащей только этот текст | |
| -o | Заново открывает терминал как стандартный ввод команды (для интерактивных программ) | |
| --process-slot-var | Записывает разный номер в переменную окружения для каждой одновременной команды |
🔲 Симулятор команды xargs
В симуляторе ниже можно самим вводить команды xargs и find на тех же тестовых файлах.
🔢 FAQ & рекомендуемые материалы
Поиск строк
Команда grep в Linux
Команда grep находит в файлах строки, совпадающие со строками и регулярными выражениями. Используйте её для поиска сразу в нескольких файлах, переданных через xargs.
Удаление файлов
Команда rm в Linux
Статья о команде rm, удаляющей файлы и папки, и об опасности опции -rf. Проверьте опции, прежде чем ставить rm после xargs.
Завершение процессов
Команда kill в Linux
Команда kill отправляет сигнал номеру процесса и завершает его. Используйте её дальше, когда передаёте список номеров процессов через xargs для завершения.
ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.