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/-dxargsсам разбирает кавычки: строка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