Команда xargs: использование, опции -n и -I и работа с find

Тестовая средаСемейство RHELAlmaLinux 9.8Учётная запись rootПроверено 2026-10-29

Команда xargs — это инструмент Linux, который превращает строки и слова со стандартного ввода в аргументы другой команды и запускает её. Когда мы в рабочей папке на сервере AlmaLinux 9 передали через xargs команде wc три файла журнала, найденные find, файл с пробелом в имени разбился на две части и возникла ошибка, а с -print0 и -0 появились количества строк всех трёх файлов.

Вывод ниже получен в рабочей папке под учётной записью root на сервере AlmaLinux 9.8. Список имён, журналы и временные файлы — это примеры, созданные для теста, а IP-адреса и пути папок в них тоже примерные значения.

1️⃣ Основы команды xargs

  • ↪️ Стандартный ввод как аргументы команды

xargs делит стандартный ввод от предыдущей команды по пробелам и переводам строки и запускает команду, указанную после него, с этими частями в качестве аргументов. Мы проверили это на файле names.txt с одним именем в строке.

cat names.txt
alice
bob
carol
dave
erin

Если передать вывод cat в xargs echo, пять строк станут аргументами одного echo и выведутся одной строкой.

cat names.txt | xargs echo
alice bob carol dave erin

Если не указать команду после него, xargs запустит echo, поэтому результат тот же.

cat names.txt | xargs
alice bob carol dave erin

Канал соединяет вывод предыдущей команды со стандартным вводом следующей, поэтому в аргументы следующей команды ничего не попадает. Если передать list.txt с тремя именами файлов в wc -l только через канал, wc посчитает 3 строки самого списка.

cat list.txt
logs/access.log
logs/error.log
tmp/keep.txt
cat list.txt | wc -l
3

Если поставить между ними xargs, три имени из списка станут аргументами wc и появится число строк для каждого файла.

cat list.txt | xargs wc -l
  3 logs/access.log
  2 logs/error.log
  1 tmp/keep.txt
  6 total

2️⃣ Опции xargs -n и -I

  • ↪️ Размер группы, позиция аргумента и проверка через -t

Без опций весь ввод попадает в один запуск команды, поэтому чтобы повторять её, задайте через -n, сколько аргументов передавать за раз. На рисунке ниже видно, как те же пять имён группируются в зависимости от опции.

🧩 Как xargs группирует стандартный ввод в аргументы команды
Поясняющая схема
⚙️ Опция
$ cat names.txt | xargs echo
$ cat names.txt | xargs -n 2 echo
$ cat names.txt | xargs -I {} echo 'user: {}'
① Стандартный ввод (names.txt)alicebobcaroldaveerinПо одному имени в строке, пять строк.
② Группировка в аргументыalicebobcaroldaveerinБез опций все пять образуют одну группу.alicebobcaroldaveerin-n 2 группирует по два, а оставшееся идёт отдельной группой.alicebobcaroldaveerin-I {} считает одну строку группой и подставляет её вместо {}.
③ Запускаемые команды и выводecho alice bob carol dave erinalice bob carol dave erinecho запускается один раз.echo alice bobecho carol daveecho erinecho запускается три раза, по одной строке на группу.echo 'user: alice' echo 'user: bob' … пять раз в том же виде до erinuser: aliceuser: bobuser: caroluser: daveuser: erinecho запускается пять раз, вместо {} подставляется имя.
Без опций xargs добавляет все слова из ввода как аргументы одного запуска команды. Пять имён уходят в один echo и выводятся одной строкой.
С -n 2 слова группируются по два, а команда повторяется. Пять имён образуют три группы, поэтому echo запускается три раза.
С -I {} одна строка считается единицей, она подставляется вместо {} в команде, и команда запускается для каждой строки. Это нужно, когда аргумент должен стоять не в самом конце.

-n 1 запускает echo для каждого имени, и выводится пять строк.

cat names.txt | xargs -n 1 echo
alice
bob
carol
dave
erin

-n 2 группирует по два, а оставшееся передаёт отдельно.

cat names.txt | xargs -n 2 echo
alice bob
carol dave
erin

Чтобы увидеть запускаемые команды, добавьте -t. Сначала выводится строка команды, а под ней её вывод.

cat names.txt | xargs -t -n 2 echo
echo 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: erin
cat names.txt | xargs -I {} echo '{} -> home/{}'
alice -> home/alice
bob -> home/bob
carol -> home/carol
dave -> home/dave
erin -> home/erin

Тем же способом можно создать папку для каждого имени. Сначала создайте папку home, а затем через -I {} создайте в ней папки по именам: появится пять папок.

mkdir home
cat names.txt | xargs -I {} mkdir home/{}
ls home
alice  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 echo
alice bob
carol dave
erin

3️⃣ Связка find и xargs

  • ↪️ Передача имён файлов с пробелами через -print0 и -0

Список имён не нужно создавать вручную: найденные 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.log

4️⃣ Удаление файлов командой xargs

  • ↪️ Сначала посмотреть через echo и подтвердить через -p

Если поставить rm после xargs, найденные файлы удалятся за один раз, поэтому перед удалением проверьте, какие файлы будут переданы. Если поставить echo перед rm, выведется только строка команды, которая запустилась бы, а файлы останутся на месте.

find /root/work/tmp -name '*.tmp' -print0 | xargs -0 echo rm
rm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp
ls tmp
cache-a.tmp  cache-b.tmp  cache-c.tmp  keep.txt

С -p xargs спрашивает о каждой команде, запускать ли её. Если ввести n, ничего не удаляется и три временных файла остаются.

find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rm
rm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...n
ls tmp
cache-a.tmp  cache-b.tmp  cache-c.tmp  keep.txt

Если ввести y, три файла удаляются и остаётся только keep.txt.

find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rm
rm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...y
ls tmp
keep.txt

Если ввод пуст, xargs один раз запускает команду без аргументов. При передаче пустого файла rm запускается без аргументов и выдаёт ошибку [rm: missing operand]; с -r команда вообще не запускается.

cat empty.txt | xargs rm
rm: missing operand
Try 'rm --help' for more information.
cat empty.txt | xargs -r rm

5️⃣ Параллельный запуск, разделители и опции xargs

  • ↪️ Опции -P, -d и -a

🔲 Параллельный запуск и разделители

Когда команды идут по одной, при большом числе целей время растёт. -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.003s
time 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 echo
alice
bob
carol

Чтобы читать из файла вместо стандартного ввода, укажите имя файла в -a. Пять имён из names.txt ушли в echo без канала.

xargs -a names.txt echo
alice 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 на тех же тестовых файлах.

Симулятор команды xargsGNU findutils 4.8
[root@server work]#
Клавишами ↑↓ можно вызвать ранее введённые команды.

🔢 FAQ & рекомендуемые материалы

Если передать номер процесса, kill отправит сигнал этому номеру. Когда мы получили номер процесса sleep 600, запущенного в фоне, через переменную оболочки $! и передали его в xargs kill, в списке заданий осталось [Terminated sleep 600], а при следующем jobs задание исчезло. Если собираете номера другой командой, сначала выведите, какие процессы туда попали, и только потом передавайте.

Опция --show-limits выводит пределы. На тестовом сервере верхний предел POSIX для длины строки команды составил 2,093,890 байт, а буфер команды, который реально использует xargs, — 131,072 байта. Согласно руководству, если ввод длиннее этого буфера, xargs разбивает команду на несколько запусков.

Если хотя бы одна команда, запущенная xargs, завершается с кодом от 1 до 125, код выхода xargs равен 123. И запуск wc с разбитым именем файла, и запуск rm с пустым вводом дали 123, а не найденная команда дала 127. Ориентируйтесь на эти значения при проверке кода выхода после xargs в скриптах оболочки.

ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Докажите, что вы человек: 5   +   4   =