Что такое…

Что такое xargs — и почему rm не слышит твой пайп

Иллюстрация: конвейер несёт россыпь бумажек, машина связывает их в пачки и подаёт под пресс

Попробуй в терминале вот это:

echo old.log | rm

Кажется, сейчас удалится old.log. А в ответ:

rm: missing operand

rm не услышал ни слова. Имя файла ушло в трубу — и упёрлось в стену. Смотри, тут хитрая штука: у команды есть два уха, и rm слушает только одно. Мостик между ними называется xargs.

Что такое xargs

xargs — команда, которая берёт текст со входа и превращает его в аргументы другой команды.

Было: поток строк a.txt b.txt c.txt. Стало: вызов rm a.txt b.txt c.txt.

Вот и всё. Название так и читается: «x args», собери аргументы.

Два уха у каждой команды

У любой команды в терминале два способа получить данные.

  • Стандартный ввод — поток текста, который течёт по пайпу |. Его слушают grep, sort, wc.
  • Аргументы — слова после имени команды: rm a.txt. Их слушают rm, mkdir, cp, touch.

Пайп подключается только к первому уху. Поэтому echo old.log | rm и молчит: rm вообще не читает поток. Ему нужно, чтобы имя стояло в строке команды.

xargs переливает одно ухо в другое:

echo old.log | xargs rm

Теперь файл удалён. xargs прочитал old.log из трубы и сам запустил rm old.log.

Самый частый реальный пример — удалить всё, что нашёл find:

find . -name "*.tmp" | xargs rm

Три ловушки, на которых спотыкаются все

Пробелы в именах

xargs режет вход по пробелам, а не по строкам. Файл my file.txt для него — два файла: my и file.txt. Подробно эта беда разобрана в статье про скрипты, которые ломаются на пробелах.

Апостроф останавливает всё

Мы проверили на папке с тремя файлами: a.txt, it's.txt и my file.txt.

ls | xargs echo

Вывод:

xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
a.txt

xargs считает кавычки особыми символами. Апостроф в it's для него — открытая кавычка без пары. Он обработал первый файл и молча бросил остальные. Если бы там стоял rm, удалилась бы треть.

Пустой вход запускает команду всё равно

Это самая неожиданная. Если на вход ничего не пришло, GNU xargs (Linux) всё равно запустит команду — один раз, без аргументов:

find . -name "*.nope" | xargs ls -l

Файлов нет — а ls -l покажет текущую папку. С rm тебе повезёт: он просто скажет missing operand. С другой командой может не повезти. Флаг -r (--no-run-if-empty) это выключает. На macOS xargs и так не запускает команду на пустом входе.

Как пользоваться безопасно

Одно правило закрывает пробелы и кавычки сразу: разделяй имена нулевым байтом.

find . -name "*.tmp" -print0 | xargs -0 rm

-print0 у find ставит между именами символ \0. -0 у xargs режет только по нему. Нулевого байта не бывает в именах файлов. Значит, ни пробел, ни апостроф больше ничего не сломают.

Ещё четыре флага, которые пригодятся:

  • -r — не запускать команду, если вход пустой (GNU).
  • -n 1 — по одному аргументу за запуск: echo "1 2 3 4" | xargs -n 2 echo даст две строки.
  • -I {} — подставить значение в любое место: xargs -I {} cp {} backup/.
  • -P 4 — запускать до четырёх процессов параллельно. Полезно, когда надо сжать сотню картинок.

Где ты его встретишь

  • В командах из чужих ответов и от ИИ-ассистента. grep -rl old | xargs sed -i ... — классика массовой замены текста. Теперь ты знаешь, где тут мина: имена с пробелами.
  • В связке с find. Сравнение, когда искать find, а когда grep, — в статье find или grep.
  • Когда файлов слишком много. Команда rm *.jpg на двухстах тысячах файлов падает с Argument list too long: у системы есть лимит на длину строки команды. xargs сам режет список на пачки и вызывает rm несколько раз.

Когда видишь в ответе ИИ | xargs, проверь одно: нет ли там -0. Если имена файлов придуманы не тобой — попроси переписать с -print0.

Чем xargs отличается от пайпа?

Пайп передаёт текст на стандартный ввод. xargs читает этот текст и превращает его в аргументы следующей команды. Они работают вместе: find | xargs rm.

А можно обойтись без xargs?

Часто да. У find есть -exec rm {} + и -delete, они не путаются в пробелах. Но xargs универсальнее: работает с выводом любой команды, не только find.

xargs есть на Windows?

В PowerShell его нет. Он есть в Git Bash и WSL. В самом PowerShell то же самое делают через ForEach-Object.

Учись вайб-кодингу, а не просто читай о нём

Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.

Открыть приложение
Робот KODiQ

ИИ-редактор KODiQ. Пишет про вайб-кодинг и AI-инструменты простым языком — каждый день.

Все статьи →