Используем инструменты: Grep, Xargs и Sed. Xargs: многообразие вариантов использования

Недавно я был вдохновлен на написание этого поста после того когда я наткнулся на ситуации когда мне нужно было отредактировать несколько файлов из проекта и заменить одни слова на другие. Раньше я это делал через Notepad++ (CTRL + H), но это хорошо если мы знаем в каком файле нам надо заменить слово, а если этих файлов тысячи. Так вот я хочу вам представить 3 базовых инструмента системы UNIX на сегодняшний день: grep , xargs , и sed .

Вы могли уже слышать они и раньше и уже знаете как ими пользоваться то вы но верно ничего нового уже не узнаете. Но если вы хотите узнать основы по использованию этих инструментов читайте дальше.

Grep

Grep является базой Unix командной для поиска фраз как из стандартного потока так и файлов. Grep возвращает информацию по файлам которые содержат вашу фразу и немного информации о том, где они находятся. Вот пример стандартного способа использование Grep:

Grep "footer" index.html

Теперь добавим несколько опции для поиска:

  • i - Игнорирует регистр символов при сравнениях.
  • n - Выдает перед каждой строкой ее номер в файле.
  • b - Выдает номер столбца в найдено файле.
grep -i -n -b "footer" index.html

А теперь поиск по цельным словам:

  • w - Ведет поиск по цельным словам. Например при обычном поиске строки text grep может найти слово textarea . А если используется данный ключ то будут найдены только строки где есть слово text.
grep -w "text" index.html

Поиск по файлу это хорошо но лучше если мы сможем искать файлы рекурсивно по проекту.

  • r - Рекурсивный поиск файлов из текущей директории.
  • l - Выдает только имена файлов, содержащие искомое значение.
grep -r -l "footer" ./

А теперь попробуем вывести файлы в которых нет искомого значения.

  • L - Выводит имена файлов в которых нету искомого значения.
grep -r -L -i "footer" ./

Также очень часто нам надо искать в конкретных типах файлов данное значения.

grep -r --include="*.html" -l "footer" ./

Поиск по файлам которые начинаются на index и заканчиваются на.php

Grep -r --include="index*.php" -l "footer" ./

Теперь давайте передадим результат работы в файл.

Grep -r -l "footer" ./ > out.txt

Xargs

Это удивительная команда работает по прицепу, берет данные из стандартного ввода или из файла, разбивает их в соответствии с указанными параметрами, а затем передает другой программе в качестве аргумента. Xargs выполняется до тех пор пока данные из потока не исчерпаны. Теперь давайте рассмотрим несколько простых примеров.

Разбивай стандартный поток на аргументы.

  • –n - Указываем количество возвращаемых аргументов.
echo 1 2 3 4 | xargs -n 1

Теперь зададим разделитель аргументов.

  • –d - Указывает на разделитель для вывода аргументов.
echo "1-2-3-4" | xargs -d "-" -n 1

Вот более интересный пример где xargs используется для передачи файлов которых надо удалить.

Find . -name "*.txt"| xargs rm -rf

Вся суть использования xargs это дробления входящих аргументов для последующей передачи аргументов другим программам.

Sed

Sed - это потоковый редактор который принимает текст либо с стандартного потока, либо из текстового файла, выполняет некоторые операции над строками и затем выводит результат на стандартный вывода или в файл. Как правило, в сценариях, sed используется в конвейерной обработке данных, совместно с другими командами и утилитами.

Делаем простую замену строк из файла text.txt и сохраняем в файл out.txt.

Sed "s/text/test/g" text.txt > out.txt

А теперь сохраним все изменения в текущий файл.

  • i - для записи изменений в текущий файл.
sed -i "s/text/test/g" text.txt

Комбинируем все вмести

Комбинируя эти три команды, которые являются общими для всех unix систем, мы можем сделать довольно мощный сценарий для замены текста. Большая часть действий происходит от использования команды sed, но другие команды являются вспомогательным для построения запроса. Теперь давайте рассмотрим пример использования всех трех программ вымести:

Grep -r -l "foo" ./ | xargs sed -i "s/foo/bar/g"

Таким образом мы смогли заменить все foo на bar используя простую комбинацию из этих программ.

Теперь когда мы узнали основы по работе таких замечательных инструментах как grep, xargs и sed. Мы сможем писать более продвинутых сценарии для наших задач.

Об утилите xargs написано очень много — что можно написать еще? Но если, что называется, копнуть поглубже, то выясняется, что во многих публикациях излагаются лишь самые основы, но нет главного: не объясняется, как можно применять xargs в реальной практике. Статей с разбором сложных и нетривиальных вариантов применения этого весьма полезного для системного администратора инструмента, к сожалению, очень мало. Именно поэтому мы написали свою статью и постарались включить в нее как можно больше примеров использования xargs для решения различных проблем.

Сначала мы рассмотрим принцип работы xargs и разберем примеры попроще, а затем перейдем к разбору сложных и интересных кейсов.

Вспоминаем основы

Принцип работы xargs можно описать следующим образом: программа берет данные из стандартного ввода или из файла, разбивает их в соответствии с указанными параметрами, а затем передает другой программе в качестве аргумента.

В общем виде синтаксис команды xargs можно представить так:

[команда_генератор_списка] | xargs [опции_xargs] [команда]
Рассмотрим, как все это работает, на материале простых и хрестоматийных примеров.

Удаление файлов

Одна из самых частых ситуаций, в которых используется xargs — удаление файлов, найденных при помощи команды find.

Представим себе следующую ситуацию: имеется директория, в которой хранится большое количество файлов. Из нее нужно удалить файлы определенного типа (в нашем примере — файлы с расширением *.sh). Чтобы осуществить эту операцию, нужно передать xargs вывод команды find, и к файлам с указанным расширением будет применена команда -rm:

$ ls one.sh one.py two.sh two.py $ find . -name "*.sh"| xargs rm -rf $ ls one.py two.py

Отметим, что операцию удаления файлов можно осуществить и без xargs, а с помощью команды

$ find . -name "*.sh" -exec rm -rf "{}" \

Описанный способ не сработает, если в имени одного из удаляемых файлов содержится пробел. Имя, состоящее из двух слов, разделенных пробелом, не будет воспринято как единое целое.

Проиллюстрируем это следующим примером:

$ ls new file.sh one.sh one.py two.sh two.py $ find . -name "*.sh"| xargs rm -rf $ ls new file.sh one.py two.py

Как видим, файл, в имени которого имеется пробел, не был удалён.

Чтобы решить эту проблему, используется опция print0 для команды find и опция -0 для команды xargs. Она заменяет стандартный разделитель (перенос строки на нуль-символ (\x0), который и означает конец хранимой строки:

$ find . -name "*.sh" -print0 | xargs -0 rm -rf

Xargs может также помочь, например, быстро удалить все временные файлы, имеющие расширение tmp:

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

Сжатие файлов

Сжать все файлы в текущей директории с помощью gzip можно, введя следующую команду:

$ ls | xargs -p -l gzip

Рассмотрим еще один пример: сжатие с помощью tar всех файлов с расширением *.pl:

$ find . -name "*.pl" | xargs tar -zcf pl.tar.gz

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

С помощью xargs можно осуществлять массовое переименование файлов. Представим себе, что у нас есть группа файлов с расширением *.txt, и нам нужно заменить это расширение на *.sql. Это можно сделать при помощи xargs и потокового текстового редактора sed:

$ ls | sed -e "p;s/.txt$/.sql/" | xargs -n2 fmv

В результате ее выполнения на консоль будет выведен список переименованных файлов.

С помощью xargs можно также добавлять к дополнительные элементы к именам файлов (например, дату):

$ ls | xargs -I FILE mv {} <...>-{}

Вместо <..> можно подставить всё, что угодно.
Фигурные скобки {} в этом примере означают «текущий аргумент» (т.е. текущее имя файла).

Изменение прав для папок и файлов

С помощью xargs можно также ускорить процесс смены прав на файлы и папки для определенного пользователя или группы. Предположим, нам нужно найти все папки пользователя root и заменить их владельца на temp. Эта операция осуществляется при помощи команды:

$ find . -group root -print | xargs chown temp

Чтобы найти все папки группы root и заменить группу на temp, используется команда:

$ find . -group root -print | xargs chgrp temp

Xargs и find: сложные операции

С помощью команд find и xargs можно выполнять и более сложные операции. Вот так, например, можно удалить временные файлы, созданные более 7 дней назад:

$ find /tmp -type f -name "*" -mtime +7 -print0 | xargs -0 rm -f

А вот так — принудительно остановить процессы, которые уже работают больше 7 дней:

$ find /proc -user myuser -maxdepth 1 -type d -mtime +7 -exec basename {} \; | xargs kill -9

Xargs и сut

Xargs довольно часто используется в сочетании с командой cut, позволяющей вырезать строки из текстовых файлов. Рассмотрим некоторые практические примеры. С помощью приведённой ниже команды на консоль будет выведен список всех пользователей системы:

$ cut -d: -f1 < /etc/passwd | sort | xargs echo

А команда вида

File * | grep ASCII | cut -d":" -f1 | xargs -p vim
будет последовательно открывать файлы для редактирования в vim.
Обратим внимание на опцию -p. Благодаря ей команда будет выполняться в интерактивном режиме: перед открытием каждого файла будет запрашиваться подтверждение (y/n).

В заключение приведём ещё один сложный и интересный пример — рекурсивный поиск файлов самого большого размера в некоторой директории:

$ find . -type f -printf "%20s %p\n" | sort -n | cut -b22- | tr "\n" "\000" | xargs -0 ls -laSr

Параллельный запуск процессов

Xargs часто используется для параллельного запуска нескольких процессов. Вот так, например, можно одновременно cжать несколько директорий в tar.gz:

$ echo dir1 dir2 dir3 | xargs -P 3 -I NAME tar czf NAME.tar.gz NAME

В приведенном примере используется ключ -P. Он указывает максимальное количество процессов, которые будут выполняться одновременно. Предположим, что у нас на входе имеется 10 аргументов. Если мы введём команду xargs с ключoм -P 3, то будет запущено 3 экземпляра команды, следующей после xargs, с каждым из этих аргументов.

С помощью xargs можно также параллельно загружать из Интернета множество файлов:

В приведенном примере с указанного адреса будут скачаны все графические файлы с расширением jpg; ключ -P указывает, что требуется скачивать по 10 файлов одновременно.

Предварительные итоги

Подведём предварительные итоги и сформулируем несколько правил работы с xargs.

  1. Xargs не работает с файлами, в имени которых присутствует пробел. Для решения этой проблемы с командой xargs используется опция −0. Пробел в имени файла можно обойти также следующим образом:
    $ xargs -I FILE my_command “FILE”
  2. Команда xargs принимает команды из со стандартного ввода, разделенные пробелом или переводом строки. Чтобы группировать эти команды, можно использовать двойные или одинарные кавычки. Можно также указать разделитель с помощью опции -d;
  3. Если команде xargs не передать вообще никаких аргументов, то по умолчанию будет выполнена команда /bin/echo;
  4. Во многих случаях команду xargs можно заменить циклом for. Например, команда
    $ find . -type f -and -iname "*.deb" | xargs -n 1 dpkg -I
    полностью эквивалента циклу
    $ for file in `find . -type f -and -iname "*.deb"`; do dpkg -I "$file"; done

Нетривиальные примеры

Основы мы вспомнили, типичные варианты использования рассмотрели… Перейдем теперь к более сложным и нетривиальным примерам. До некоторых из них мы додумались самостоятельно, работая над повседневными задачами, а некоторые — почерпнули с сайта http://www.commandlinefu.com (всем желающим научиться тонкостям работы с командной строкой очень рекомендуем время от времени его посещать — там порой можно найти очень полезные советы).

Баним IP-адреса из списка

Чтобы забанить IP-адреса из списка, нужно их добавить в IP tables c правилом DROP. Эта операция осуществляется при помощи команды:

$ cat bad_ip_list | xargs -I IP iptables -A INPUT -s IP -j DROP
Можно проделать и более сложную операцию и забанить все адреса по AS:

$ /usr/bin/whois -H -h whois.ripe.net -T route -i origin AS<номер>|egrep "^route"|awk "{print $2}" |xargs -I NET iptables -A INPUT -s NET -j DROP

Изменяем формат URL

Преобразовать URL вида «http%3A%2F%2Fwww.google.com» в «www ,google.com» можно при помощи команды:

Echo "http%3A%2F%2Fwww.google.com" | sed -e"s/%\(\)/\\\\\x\1/g" | xargs echo -e

Генерируем пароль из 10 символов

Сгенерировать надежный пароль можно при помощи команды вида:

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

Генерировать пароли можно и без помощи xargs: для этого cуществует специализированная утилита pwgen. Некоторые другие способы генерации паролей описаны также .

Ищем бинарные файлы, установленные без использования dpkg

Такая операция может потребоваться в случае, если, например, машина стала жертвой хакерской атаки и на ней было установлено вредоносное программное обеспечение. Выявить, что за программы поставили злоумышленники, поможет следующая команда (она ищет запущенные «бинарники», установленные без использования менеджера пакетов dpkg):

$ сat /var/lib/dpkg/info/*.list > /tmp/listin ; ls /proc/*/exe |xargs -l readlink | grep -xvFf /tmp/listin; rm /tmp/listin

Удаляем устаревшие пакеты ядра

$ dpkg -l linux-* | awk "/^ii/{ print $2}" | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e | xargs sudo apt-get -y purge

Проблема удаления старых ядер уже обсуждалась на Хабре — см. (по этой же ссылке можно найти любопытные примеры команд).

Преобразуем скрипт в строку

Иногда возникает необходимость преобразовать большой скрипт в одну строку. Сделать это можно так:

  • селектел
  • selectel
  • Добавить метки

    Долгими зимними вечерами я сидел и думал "вот придёт светлое время, я сяду и как следует разберусь с этой загадочной утилиткой xarg". Ну вот время похоже и пришло - я сел разбираться. Первое, что мне бросилось в глаза, это то, что man к ней довольно загадочный, и с первого раза не просветляет. на википедии понимания тоже не добавила, а скорее даже запутала, поэтому я решил провести своё собственное расследование, и написать по этому поводу небольшой мануальчик. Как известно, пока объясняешь и сам поймёшь:)

    Итак, xargs.

    xargs это такая утилита командной строки, позволяющая вызвать любую команду с аргументами, взятыми из стандартного входа. Причём аргументы можно передать все сразу, а можно группировать по несколько штук. Изучать мы будем xargs версии 4.4.0, при чём по рекомендации man-а будем использовать только новые аргументы, не помеченные как deprecated(лучше сразу привыкать работать правильно).

    Итак первое, что стоит понять, это то, как xargs обрабатывает входящий поток и делит его на аргументы. Есть несколько режимов, зависящих от опций:

    1. Обычный. По умолчанию разделителем аргументов считается любой пробельный символ: пробел, табуляция, вертикальная табуляция или перевод строки. Но как и в командной оболочке можно использовать "" или \ что бы предотвратить разбиение аргумента.

    2. Обычный, с группировкой. Режим, включающийся параметром -L. Практически идентичен предыдущему, за исключением того, что xargs запоминает, какой аргумент на какой строке находится. Более того, если строка оканчивается пробелом или табуляцией, следующая строка считается продолжением текущей.

    3. По строкам. Включается при использовании опции -I или -0. При этом вся строка считается одним целым аргументом, несмотря на пробелы и табуляции внутри. Для -I концом строки является символ "\n" а для -0 символ "\0"

    Проведём пару испытаний, что бы лучше понять всё это. Создадим файл test с следующим содержимым(== в файл заносить не надо):
    ==
    arg1
    arg2 space
    "arg3 quoted"
    arg4\ escaped
    arg5 with
    continue
    ==
    (После "arg5 with" должен быть пробел)
    А так-же напишем небольшой скрипт tp, который будет выводить свои аргументы разделяя их символом ":" и количество:
    ==
    #!/bin/bash
    echo -n "@$#"
    while [[ $1 != "" ]]; do echo -n ":$1"; shift; done
    echo
    ==

    Обычный режим(выделение аргументов по пробельным символам):
    x $ cat test | xargs ./tp
    @8:arg1:arg2:space:arg3 quoted:arg4 escaped:arg5:with:continue
    Файл был разбит на аргументы по пробельным символам, но строки взятые в кавычки и экранированные символом "\" остались целыми.

    Обычный режим с группировкой по строкам не отличается от предыдущего на этом этапе.

    Разбиение по строкам. Создадим второй тестовый файл следующей командой:
    x $ cp test testz && printf "\0arg6" >> testz
    Проверим
    x $ cat testz | xargs -0 ./tp
    @2:arg1
    arg2 space
    "arg3 quoted"
    arg4\ escaped
    arg5 with
    continue
    :arg6

    Как можно видеть аргумента всего 2. Первый длинный, сохранивший переводы строк, кавычки и \, а второй arg6. В файле они разделены нулевым символом.

    По поводу разделения параметров можно ещё сказать о опции -d, которая указывает новый разделитель. Например попробуем использовать "3" как разделитель.
    x $ cat test | xargs -d 3 ./tp
    @2:arg1
    arg2 space
    "arg: quoted"
    arg4\ escaped
    arg5 with
    continue
    Произошло разделение файла на 2 части на месте символа "3". Что примечательно, таким образом можно эмулировать опцию -0
    x $ cat testz | xargs -d "\x00" ./tp
    @2:arg1
    arg2 space
    "arg3 quoted"
    arg4\ escaped
    arg5 with
    continue
    :arg6

    С деление входного потока на аргументы кажется разобрались, переходим к подстановке параметров.

    Итак, xarg после своих опций ждёт команду, которую и будет выполнять. Все входящие аргументы разбиваются на группы, после чего заданная команда вызывается для каждой группы, и в неё передаются все аргументы из этой группы.

    Теперь рассмотрим, как формируются группы.

    1. Если опций нет, то группа одна, в неё попадают все аргументы из потока ввода. Группа бесконечного размера, так сказать:)

    2. Опция -L n задаёт группировку по строкам. В команду передаются аргументы находящиеся на n строках. Продемонстрирую на примерах.
    Группировка по 1 строке:
    x $ cat test | xargs -L 1 ./tp
    @1:arg1
    @2:arg2:space
    @1:arg3 quoted
    @1:arg4 escaped
    @3:arg5:with:continue
    Видно, что вторая строка содержит 2 аргумента, потому как они оба на одной строке. А а последняя вообще 3, так как предпоследняя строка "удлинняется" за счёт пробела в конце.

    Теперь группировка по 2 строки. В команду попадают строки 1 и 2; 3 и 4; и сиротка 5-ая:
    x $ cat test | xargs -L 2 ./tp
    @3:arg1:arg2:space
    @2:arg3 quoted:arg4 escaped
    @3:arg5:with:continue

    3. Группировка по аргументам, задаваемая опцией -n x. Тут всё прозрачно: аргументы группируются по x штук и передаются в команду.
    По одному аргументу:
    x $ cat test | xargs -n 1 ./tp
    @1:arg1
    @1:arg2
    @1:space
    @1:arg3 quoted
    @1:arg4 escaped
    @1:arg5
    @1:with
    @1:continue
    По 2 аргумента:
    x $ cat test | xargs -n 2 ./tp
    @2:arg1:arg2
    @2:space:arg3 quoted
    @2:arg4 escaped:arg5
    @2:with:continue

    3. Режим с подстановкой - опция -I. Для начала надо напомнить, что в данном режиме аргументы из потока ввода разбираются по особому. Каждая строка это один целый аргумент, склеивание строк не производится. Во вторых, у опции -I имеется параметр - строка, которая заменяется в команде на аргумент:
    x $ echo -e "A B\nC D" | xargs -I _ ./tp =_+_=
    @1:=A B+A B=
    @1:=C D+C D=
    Легко заметить, что символ _ задан как строка подстановки аргумента, которая используется в команде 2 раза. Так же видно, что аргументы выделяются целыми строками, и пробел не влияет на разбор. Команда вызывается для каждого аргумента.

    С подстановкой всё. Рассмотрим оставшиеся важные опции
    -r - не выполнять команду, если нет аргументов:
    x $ cat /dev/null | xargs ./tp
    @0
    x $ cat /dev/null | xargs -r ./tp
    x $
    Как видим, во втором случае команда не выполнилась.

    P - xargs будет запрашивать подтверждение на выполнение каждой команды.

    На этом небольшой мануал завершён. Он оказался не совсем кратеньким, зато надеюсь понятненьким;)

    Об утилите xargs написано очень много — что можно написать еще? Но если, что называется, копнуть поглубже, то выясняется, что во многих публикациях излагаются лишь самые основы, но нет главного: не объясняется, как можно применять xargs в реальной практике. Статей с разбором сложных и нетривиальных вариантов применения этого весьма полезного для системного администратора инструмента, к сожалению, очень мало. Именно поэтому мы написали свою статью и постарались включить в нее как можно больше примеров использования xargs для решения различных проблем.

    Сначала мы рассмотрим принцип работы xargs и разберем примеры попроще, а затем перейдем к разбору сложных и интересных кейсов.

    Вспоминаем основы

    Принцип работы xargs можно описать следующим образом: программа берет данные из стандартного ввода или из файла, разбивает их в соответствии с указанными параметрами, а затем передает другой программе в качестве аргумента.

    В общем виде синтаксис команды xargs можно представить так:

    [команда_генератор_списка] | xargs [опции_xargs] [команда]
    Рассмотрим, как все это работает, на материале простых и хрестоматийных примеров.

    Удаление файлов

    Одна из самых частых ситуаций, в которых используется xargs — удаление файлов, найденных при помощи команды find.

    Представим себе следующую ситуацию: имеется директория, в которой хранится большое количество файлов. Из нее нужно удалить файлы определенного типа (в нашем примере — файлы с расширением *.sh). Чтобы осуществить эту операцию, нужно передать xargs вывод команды find, и к файлам с указанным расширением будет применена команда -rm:

    $ ls one.sh one.py two.sh two.py $ find . -name "*.sh"| xargs rm -rf $ ls one.py two.py

    Отметим, что операцию удаления файлов можно осуществить и без xargs, а с помощью команды

    $ find . -name "*.sh" -exec rm -rf "{}" \

    Описанный способ не сработает, если в имени одного из удаляемых файлов содержится пробел. Имя, состоящее из двух слов, разделенных пробелом, не будет воспринято как единое целое.

    Проиллюстрируем это следующим примером:

    $ ls new file.sh one.sh one.py two.sh two.py $ find . -name "*.sh"| xargs rm -rf $ ls new file.sh one.py two.py

    Как видим, файл, в имени которого имеется пробел, не был удалён.

    Чтобы решить эту проблему, используется опция print0 для команды find и опция -0 для команды xargs. Она заменяет стандартный разделитель (перенос строки на нуль-символ (\x0), который и означает конец хранимой строки:

    $ find . -name "*.sh" -print0 | xargs -0 rm -rf

    Xargs может также помочь, например, быстро удалить все временные файлы, имеющие расширение tmp:

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

    Сжатие файлов

    Сжать все файлы в текущей директории с помощью gzip можно, введя следующую команду:

    $ ls | xargs -p -l gzip

    Рассмотрим еще один пример: сжатие с помощью tar всех файлов с расширением *.pl:

    $ find . -name "*.pl" | xargs tar -zcf pl.tar.gz

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

    С помощью xargs можно осуществлять массовое переименование файлов. Представим себе, что у нас есть группа файлов с расширением *.txt, и нам нужно заменить это расширение на *.sql. Это можно сделать при помощи xargs и потокового текстового редактора sed:

    $ ls | sed -e "p;s/.txt$/.sql/" | xargs -n2 fmv

    В результате ее выполнения на консоль будет выведен список переименованных файлов.

    С помощью xargs можно также добавлять к дополнительные элементы к именам файлов (например, дату):

    $ ls | xargs -I FILE mv {} <...>-{}

    Вместо <..> можно подставить всё, что угодно.
    Фигурные скобки {} в этом примере означают «текущий аргумент» (т.е. текущее имя файла).

    Изменение прав для папок и файлов

    С помощью xargs можно также ускорить процесс смены прав на файлы и папки для определенного пользователя или группы. Предположим, нам нужно найти все папки пользователя root и заменить их владельца на temp. Эта операция осуществляется при помощи команды:

    $ find . -group root -print | xargs chown temp

    Чтобы найти все папки группы root и заменить группу на temp, используется команда:

    $ find . -group root -print | xargs chgrp temp

    Xargs и find: сложные операции

    С помощью команд find и xargs можно выполнять и более сложные операции. Вот так, например, можно удалить временные файлы, созданные более 7 дней назад:

    $ find /tmp -type f -name "*" -mtime +7 -print0 | xargs -0 rm -f

    А вот так — принудительно остановить процессы, которые уже работают больше 7 дней:

    $ find /proc -user myuser -maxdepth 1 -type d -mtime +7 -exec basename {} \; | xargs kill -9

    Xargs и сut

    Xargs довольно часто используется в сочетании с командой cut, позволяющей вырезать строки из текстовых файлов. Рассмотрим некоторые практические примеры. С помощью приведённой ниже команды на консоль будет выведен список всех пользователей системы:

    $ cut -d: -f1 < /etc/passwd | sort | xargs echo

    А команда вида

    File * | grep ASCII | cut -d":" -f1 | xargs -p vim
    будет последовательно открывать файлы для редактирования в vim.
    Обратим внимание на опцию -p. Благодаря ей команда будет выполняться в интерактивном режиме: перед открытием каждого файла будет запрашиваться подтверждение (y/n).

    В заключение приведём ещё один сложный и интересный пример — рекурсивный поиск файлов самого большого размера в некоторой директории:

    $ find . -type f -printf "%20s %p\n" | sort -n | cut -b22- | tr "\n" "\000" | xargs -0 ls -laSr

    Параллельный запуск процессов

    Xargs часто используется для параллельного запуска нескольких процессов. Вот так, например, можно одновременно cжать несколько директорий в tar.gz:

    $ echo dir1 dir2 dir3 | xargs -P 3 -I NAME tar czf NAME.tar.gz NAME

    В приведенном примере используется ключ -P. Он указывает максимальное количество процессов, которые будут выполняться одновременно. Предположим, что у нас на входе имеется 10 аргументов. Если мы введём команду xargs с ключoм -P 3, то будет запущено 3 экземпляра команды, следующей после xargs, с каждым из этих аргументов.

    С помощью xargs можно также параллельно загружать из Интернета множество файлов:

    В приведенном примере с указанного адреса будут скачаны все графические файлы с расширением jpg; ключ -P указывает, что требуется скачивать по 10 файлов одновременно.

    Предварительные итоги

    Подведём предварительные итоги и сформулируем несколько правил работы с xargs.

    1. Xargs не работает с файлами, в имени которых присутствует пробел. Для решения этой проблемы с командой xargs используется опция −0. Пробел в имени файла можно обойти также следующим образом:
      $ xargs -I FILE my_command “FILE”
    2. Команда xargs принимает команды из со стандартного ввода, разделенные пробелом или переводом строки. Чтобы группировать эти команды, можно использовать двойные или одинарные кавычки. Можно также указать разделитель с помощью опции -d;
    3. Если команде xargs не передать вообще никаких аргументов, то по умолчанию будет выполнена команда /bin/echo;
    4. Во многих случаях команду xargs можно заменить циклом for. Например, команда
      $ find . -type f -and -iname "*.deb" | xargs -n 1 dpkg -I
      полностью эквивалента циклу
      $ for file in `find . -type f -and -iname "*.deb"`; do dpkg -I "$file"; done

    Нетривиальные примеры

    Основы мы вспомнили, типичные варианты использования рассмотрели… Перейдем теперь к более сложным и нетривиальным примерам. До некоторых из них мы додумались самостоятельно, работая над повседневными задачами, а некоторые — почерпнули с сайта http://www.commandlinefu.com (всем желающим научиться тонкостям работы с командной строкой очень рекомендуем время от времени его посещать — там порой можно найти очень полезные советы).

    Баним IP-адреса из списка

    Чтобы забанить IP-адреса из списка, нужно их добавить в IP tables c правилом DROP. Эта операция осуществляется при помощи команды:

    $ cat bad_ip_list | xargs -I IP iptables -A INPUT -s IP -j DROP
    Можно проделать и более сложную операцию и забанить все адреса по AS:

    $ /usr/bin/whois -H -h whois.ripe.net -T route -i origin AS<номер>|egrep "^route"|awk "{print $2}" |xargs -I NET iptables -A INPUT -s NET -j DROP

    Изменяем формат URL

    Преобразовать URL вида «http%3A%2F%2Fwww.google.com» в «www ,google.com» можно при помощи команды:

    Echo "http%3A%2F%2Fwww.google.com" | sed -e"s/%\(\)/\\\\\x\1/g" | xargs echo -e

    Генерируем пароль из 10 символов

    Сгенерировать надежный пароль можно при помощи команды вида:

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

    Генерировать пароли можно и без помощи xargs: для этого cуществует специализированная утилита pwgen. Некоторые другие способы генерации паролей описаны также .

    Ищем бинарные файлы, установленные без использования dpkg

    Такая операция может потребоваться в случае, если, например, машина стала жертвой хакерской атаки и на ней было установлено вредоносное программное обеспечение. Выявить, что за программы поставили злоумышленники, поможет следующая команда (она ищет запущенные «бинарники», установленные без использования менеджера пакетов dpkg):

    $ сat /var/lib/dpkg/info/*.list > /tmp/listin ; ls /proc/*/exe |xargs -l readlink | grep -xvFf /tmp/listin; rm /tmp/listin

    Удаляем устаревшие пакеты ядра

    $ dpkg -l linux-* | awk "/^ii/{ print $2}" | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e | xargs sudo apt-get -y purge

    Проблема удаления старых ядер уже обсуждалась на Хабре — см. (по этой же ссылке можно найти любопытные примеры команд).

    Преобразуем скрипт в строку

    Иногда возникает необходимость преобразовать большой скрипт в одну строку. Сделать это можно так: Добавить метки