← Весь справочник

xargs

Превращает строки со стандартного ввода в аргументы команды

xargs читает со стандартного ввода слова или строки и подставляет их как аргументы команде. Так вывод find, grep -l или cat список становится списком файлов для rm, chmod, wc и других команд, которые не читают stdin.

Синтаксис

команда-источник | xargs [опции] [команда [начальные аргументы…]]
xargs -a файл [опции] [команда …]

По умолчанию xargs делит ввод по пробелам, табуляциям и переводам строк, понимает кавычки и \, собирает как можно больше слов и запускает команду как можно реже. Без команды запускает echo.

Как делить ввод

ОпцияЧто делает
(по умолчанию)элементы разделены пробелами и переводами строк; кавычки '…', "…" и \ склеивают слова
-0элементы разделены нулевым байтом, кавычки не особенные — пара для find -print0, grep -lZ, sort -z
-d '\n'свой разделитель (один символ): -d '\n' — строки целиком, -d , — через запятую; кавычки не особенные
-a файлчитать элементы из файла, а stdin оставить команде
-E СТОПпрекратить чтение, встретив элемент СТОП

Сколько аргументов на запуск

ОпцияЧто делает
-n Nне больше N аргументов на один запуск
-L Nне больше N непустых входных строк на запуск
-I{}подставить элемент вместо {} в любом месте команды; элемент — вся строка; запуск на каждую строку
-s Nне длиннее N символов на командную строку
-xзавершиться с ошибкой, если элемент не влезает в -s/-n
--show-limitsпоказать системный предел длины командной строки

Как запускать

ОпцияЧто делает
-rне запускать команду, если ввод пустой (GNU)
-P Nзапускать до N команд параллельно; -P 0 — сколько получится
--process-slot-var=VARпри -P передать каждому запуску номер слота в переменной VAR
-tпечатать каждую команду в stderr перед запуском
-pспрашивать подтверждение перед каждым запуском (нужен терминал)
-oподключить stdin команды к терминалу — для интерактивных программ (vim)

Код возврата

КодКогда
0все запуски команды завершились успешно
123хотя бы один запуск вернул 1–125
124команда вернула 255 — xargs прекратил работу
125команду убил сигнал
126 / 127команда не запускается / не найдена
1ошибка самого xargs (например, непарная кавычка)

Примеры

# удалить все .tmp, имена с пробелами не ломаются
find . -name '*.tmp' -print0 | xargs -0 rm --

# посчитать строки во всех .conf, где встречается слово listen
grep -lZ 'listen' /etc/nginx/*.conf | xargs -0 wc -l

# по два аргумента на запуск: видно, как xargs режет ввод
echo a b c d e | xargs -n 2 echo

# подставить элемент в середину команды
ls *.log | xargs -I{} cp {} /srv/backup/{}.old

# каждая строка — один аргумент, даже если в ней пробелы
cat files.txt | xargs -d '\n' ls -l

# элементы через запятую
printf 'alpha,beta,gamma' | xargs -d , -n 1 echo

# сначала посмотреть, что будет запущено
find /var/log -name '*.gz' | xargs -t ls -lh

# сжать файлы в 4 потока, по одному файлу на gzip
find /srv/app/logs -name '*.log' -print0 | xargs -0 -n 1 -P 4 gzip

# своя логика на каждый элемент: аргумент приходит в $1
find . -name '*.csv' -print0 | xargs -0 -n 1 sh -c 'echo "$1: $(wc -l < "$1") строк"' _

# ничего не делать, если find ничего не нашёл
find . -name '*.bak' -print0 | xargs -0 -r rm --

# список хостов из файла, stdin остаётся свободным
xargs -a hosts.txt -n 1 ping -c 1

Подводные камни

  • Пробелы в именах. Без -0 файл my file.txt превратится в два аргумента my и file.txt. Используй find -print0 | xargs -0 или -d '\n'.
  • Кавычки особенные. Без -0/-d xargs сам разбирает кавычки: строка it's даёт ошибку «unmatched single quote», и команда не запускается.
  • Пустой ввод. GNU xargs по умолчанию всё равно запускает команду один раз — без аргументов. xargs ls на пустом вводе покажет текущий каталог, а xargs rm выдаст ошибку. Добавь -r.
  • -I меняет режим: элемент — это вся строка целиком (пробелы не режут её, начальные пробелы отбрасываются), а команда запускается отдельно для каждой строки. Это медленнее, чем пачкой.
  • -L и пробел в конце строки. Строка, оканчивающаяся пробелом, считается продолжающейся: a и b попадут в один запуск.
  • -d , не отрезает перевод строки в конце ввода: у echo 'a,b' | xargs -d , … последний элемент будет b с \n. Подавай ввод без него (printf) или режь по -d '\n' после tr ',' '\n'.
  • -n и -L взаимоисключающие — действует последняя указанная, xargs предупредит.
  • Не подставляй {} внутрь sh -c '…'. Имя файла с ; или $(…) выполнится как код. Передавай элемент аргументом: sh -c '… "$1"' _.
  • stdin команды — /dev/null. Программа, которая ждёт ввод (read, vim), ничего не получит. Для интерактивных команд — -o, для чтения списка из файла — -a.
  • Порядок при -P не гарантирован: вывод параллельных запусков перемешивается.

См. также

find · grep · rm · redirection · exit-codes · background