1 of 25

xargs

2 of 25

xargs

  1. Принимает поток символов
  2. Принимает команду которая она будет выполнять
  3. Разбивает поток символов на сегменты согласно символу-разделителю (-d)
  4. Собирает команды путём конкатенации команды из пункта 2 и очередного сегмента из пункта 3
  5. Выполняет такие команды

3 of 25

Красивая картинка №1

4 of 25

У xargs тоже есть аргументы

Полная команда

Левая часть

Правая часть

xargs rm -rf

xargs

rm -rf

xargs -p -l gzip

xargs -p -l

gzip

xargs tar -zcf pl.tar.gz

xargs

tar -zcf pl.tar.gz

xargs -I file mv

xargs -I file

mv

5 of 25

Красивая картинка

6 of 25

Выполним команду

main.cpp

main.h

version.cpp

version.h

config.cpp

config.h

data.cpp

data.h

$find . -name "*.cpp" | xargs rm -rf

7 of 25

Результат

Файлы удалятся!

8 of 25

Результат

$find . -name "*.cpp" | xargs rm -rf

Файлы удалятся!

Какие команды были выполнены?

rm -rf main.cpp

9 of 25

Результат

$find . -name "*.cpp" | xargs rm -rf

Файлы удалятся!

Какие команды были выполнены?

rm -rf main.cpp

rm -rf main.h

10 of 25

Результат

$find . -name "*.cpp" | xargs rm -rf

Файлы удалятся!

Какие команды были выполнены?

rm -rf main.cpp

rm -rf main.h

Нет!

11 of 25

Результат

$find . -name "*.cpp" | xargs rm -rf

Файлы удалятся!

Какие команды были выполнены?

rm -rf main.cpp

rm -rf main.h

Нет!

rm -rf main.cpp main.h ...

12 of 25

Почему?

Потому что входной поток данных был разбит, но не для того

13 of 25

Почему?

Потому что входной поток данных был разбит, но не для того

Как решить?

find . -name "*.cpp" | xargs -n 1 rm -rf

Почему предыдущая команда сработала?

14 of 25

Почему?

Потому что входной поток данных был разбит, но не для того

Как решить?

find . -name "*.cpp" | xargs -n 1 rm -rf

Почему предыдущая команда сработала?

Потому что rm может работать с некоторыми файлами

Так может и хорошо, зачем что-то менять?

15 of 25

Почему?

Потому что входной поток данных был разбит, но не для того

Как решить?

find . -name "*.cpp" | xargs -n 1 rm -rf

Почему предыдущая команда сработала?

Потому что rm может работать с некоторыми файлами

Так может и хорошо, зачем что-то менять?

Если вход очень большой, то поток принудительно разобьётся на несколько частей. В самом неожиданном месте

16 of 25

Как понять что было вызвано?

xargs -t

  • find . -name "*.cpp" | xargs -t rm -rf
    • rm -rf ./2.cpp ./3.cpp ./1.cpp ./5.cpp ./4.cpp
  • find . -name "*.cpp" | xargs -n 1 -t rm -rf
    • rm -rf ./2.cpp
    • rm -rf ./3.cpp
    • rm -rf ./1.cpp
    • rm -rf ./5.cpp
    • rm -rf ./4.cpp

17 of 25

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

$ find . -name "*.cpp"

  • ./2.cpp
  • ./3.cpp
  • ./1.cpp
  • ./1 0.cpp
  • ./5.cpp
  • ./4.cpp

$ find . -name "*.cpp" | xargs -n 1 -t rm -rf

???

18 of 25

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

$ find . -name "*.cpp"

  • ./2.cpp
  • ./3.cpp
  • ./1.cpp
  • ./1 0.cpp

$ find . -name "*.cpp" | xargs -n 1 -t rm -rf

  • rm -rf ./2.cpp
  • rm -rf ./3.cpp
  • rm -rf ./1.cpp
  • rm -rf ./1
  • rm -rf 0.cpp

19 of 25

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

$ find . -name "*.cpp" -print0 | xargs -n 1 -t --null rm -rf

  • rm -rf ./2.cpp
  • rm -rf ./3.cpp
  • rm -rf ./1.cpp
  • rm -rf ./1 0.cpp

20 of 25

Без аргументов

Что будет если вызвать без аргументов?

tr -dc A-Za-z0-9_ < /dev/urandom | head -c 10 | xargs

21 of 25

Без аргументов

Что будет если вызвать без аргументов?

tr -dc A-Za-z0-9_ < /dev/urandom | head -c 10 | xargs

Вызовется echo:

$tr -dc A-Za-z0-9_ < /dev/urandom | head -c 10 | xargs

jfkfEldp3w

$

22 of 25

Без аргументов

Что будет если вызвать без аргументов?

tr -dc A-Za-z0-9_ < /dev/urandom | head -c 10 | xargs

Без xargs:

$tr -dc A-Za-z0-9_ < /dev/urandom | head -c 10

jfkfEldp3w $

23 of 25

Интересные опции

  • -P [максимальное_число_процессов]
  • -P 0 - так много как можно

Проблемы

  • ???

24 of 25

Интересные опции

  • -P [максимальное_число_процессов]
  • -P 0 - так много как можно

Проблемы

  • Вывод никто не обещал что будет хороший. Можно получить часть вывода одной команды, часть другой.
  • Поэтому используем parallel

25 of 25

Интересные опции

  • find . -name "*.cpp" -print0 | xargs -0 -i cp {} backup/
  • ls backup/
  • '1 0.cpp' 1.cpp 2.cpp 3.cpp