Может быть, команда xargs — не очень популярная утилита командной строки, но от этого она не становится менее полезной, особенно в сочетании с другими командами, например, find и grep. Если вы никогда не пользовались командой xargs и хотите разобраться, как она работает, данное руководство вам поможет.
Принцип действия и синтаксис
Прежде чем рассматривать примеры применения, важно разобраться с принципом действия команды. Говоря простыми словами, эта утилита считывает данные из выходных данных другой команды или стандартного потока ввода (по умолчанию) и выполняет команду, переданную в качестве аргумента. Один или несколько раз в зависимости от входных данных. Все пропуски и пробелы во входных данных воспринимаются как разделители, пустые строки игнорируются. Таким образом, в общем виде синтаксис команды следующий:
[команда-источник данных] | xargs [опции xargs] [команда-аргумент]
Если команда в качестве аргумента не передается, по умолчанию утилита выполняет команду echo. Например, в следующем примере мы просто выполнили команду без опций и ввели текст ‘Hello, World!’ в стандартный поток ввода. После нажатия Ctrl+D (чтобы сообщить xargs о завершении ввода), была автоматически выполнена команда echo, и на экран снова был выведен текст ‘Hello, World!’.
xargs
Опции
-0- Использует во входном потоке символ-разделитель NULL («\0») вместо «пробела» и «перевода строки», хорошо сочетается с опцией -print0 команды find
-l [число] -Выполнять команду для каждой группы из заданного числа непустых строк аргументов, прочитанных со стандартного ввода. Последний вызов команды может быть с меньшим числом строк аргументов. Считается, что строка заканчивается первым встретившимся символом перевода строки, если только перед ним не стоит пробел или символ табуляции; пробел/табуляция в конце сигнализируют о том, что следующая непустая строка является продолжением данной. Если число опущено, оно считается равным 1. Опция -l включает опцию -x.
-I [зам_цеп] Режим вставки: команда выполняется для каждой строки стандартного ввода, причём вся строка рассматривается как один аргумент и подставляется в начальные_аргументы вместо каждого вхождения цепочки символов зам_цеп. Допускается не более 5 начальных_аргументов, содержащих одно или несколько вхождений зам_цеп. Пробелы и табуляции в начале вводимых строк отбрасываются. Сформированные аргументы не могут быть длиннее 255 символов. Если цепочка зам_цеп не задана, она полагается равной { }. Опция -I включает опцию -x.
-n [число] Выполнить команду, используя максимально возможное количество аргументов, прочитанных со стандартного ввода, но не более заданного числа. Будет использовано меньше аргументов. Если их общая длина превышает размер (см. ниже опцию -s). Или если для последнего вызова их осталось меньше, чем заданное число. Если указана также опция -x, каждая группа из указанного числа аргументов должны укладываться в ограничение размера, иначе выполнение xargs прекращается.
-t Режим трассировки: команда и каждый построенный список аргументов перед выполнением выводится в стандартный поток ошибок.
-p Режим с приглашением: xargs перед каждым вызовом команды запрашивает подтверждение. Включается режим трассировки (-t), за счет чего печатается вызов команды, который должен быть выполнен, а за ним — приглашение ?…. Ответ y (за которым может идти что угодно) приводит к выполнению команды; при каком-либо другом ответе, включая возврат каретки, данный вызов команды игнорируется.
-x Завершить выполнение, если очередной список аргументов оказался длиннее, чем размер (в символах). Опция -x включается опциями -i и -l. Если ни одна из опций -i, -l или -n не указана, общая длина всех аргументов должна укладываться в ограничение размера.
-s [размер] Максимальный общий размер (в символах) каждого списка аргументов установить равным заданному размеру. Размер должен быть положительным числом, не превосходящим 470 (подразумеваемое значение). При выборе размера следует учитывать, что к каждому аргументу добавляется по одному символу; кроме того, запоминается число символов в имени команды.
-e [лконф_цеп] Цепочка символов лконф_цеп считается признаком логического конца файла. Если опция -e не указана, признаком конца считается подчеркивание (_). Опция -e без лконф_цеп аннулирует возможность устанавливать логический конец файла (подчеркивание при этом рассматривается как обычный символ). Команда xargs читает стандартный ввод до тех пор, пока не дойдет до конца файла или не встретит цепочку лконф_цеп.
Примеры xargs
Ниже рассмотрим наиболее часто используемые примеры команды xargs
Создание конвейеров
Команда xargs очень полезна при создании конвейеров команд. Это самый частый случай использования команды В этом случае результат выполнения предыдущей команды передается как аргумент в xargs.
Например поиск файлов, содержащих заданную строку или текст. Например, поиск всех файлов с расширением txt, содержащих текст ‘abc’, можно выполнить следующим образом:
find -name "*.txt" | xargs grep "abc"
Вот результат выполнения команды:
В данном случае команда xargs получает входные данные от команды find. И поочередно применяет название файла к команде grep. Которая в свою очередь уже ищет строку в файле.
Просмотр файлов в текущем рабочем каталоге и всех подкаталогов в двух столбцах:
find . -print | xargs -n 2 echo
Удалить файлы, созданные более 10 дней назад в директории /tmp
find /tmp -mtime +10 | xargs rm -f
Массовая смена группы пользователей.
find . -group root| xargs chgrp user
Эта команда сменит группу владельцев с root на user на все файлы и каталоги в текущей директории.
Выше приведенных примеров достаточно что бы стало понятно как можно использовать команду xargs. И на основе этих примеров строить уже свои конструкции по использованию. А пока рассмотрим еще несколько примеров.
Использование xargs с другими командами
По умолчанию xargs выполняет команду echo, но можно в явном виде указать любую другую команду. Например, можно передать в качестве аргумента команду find с опцией -name, а затем ввести в стандартном потоке ввода имя файла (или тип файлов), который вы хотите найти.
xargs find -name
Введем в стандартном потоке ввода «*.txt», что означает поиск всех файлов с расширением txt в текущей директории и всех ее поддиректориях:
Многократное выполнение команды (для каждой строки/аргумента)
В предыдущем примере нам требовался поиск файлов с расширением txt, поэтому мы ввели в строке ввода «*.txt». Но что если нужно также найти другие типы файлов, например, .log и .tmp?
Попробуйте ввести их при выполнении команды xargs после «*.txt». Вы получите ошибку следующего вида:
Это происходит потому, что xargs передает «*.txt» и «*.log» в качестве одного имени файла команде find, которая затем запускается с двумя именами файлов в качестве аргументов:
find -name "*.txt" "*.log"
Такой синтаксис не является корректным. Нам нужно, чтобы команда xargs выполнила многократное выполнение команд. Сначала передала команд find аргумент «*.txt», и мы получили результат для расширения txt. А затем был передан аргумент «*.log». Это можно реализовать при помощи опции командной строки -L.
После этой опции необходимо указать число, которое означает максимальное количество непустых строк, которые за раз передаются команде в качестве входных данных. В нашем случае это значение будет равно 1. Так как нам требуется передача команде find одной строки за раз в качестве входных данных.
Команда будет иметь следующий вид:
xargs -L 1 find -name
А результат будет следующим:
Все работает. Теперь попытаемся ввести аргументы так:
"*.txt" "*.log"
Выполнение команды вызовет ошибку, потому что ‘-L 1’ обеспечивает передачу команде find всей строки целиком.
Для таких ситуаций можно воспользоваться опцией командной строки -n.
После опции -n, как и в случае с -L, требуется указать число, означающее количество аргументов, которые xargs должна передать команде за раз. В рассматриваемом нами случае «*.txt» и «*.log» должны быть разными аргументами. Поэтому для их передачи по отдельности нужно указать опцию -n со значением 1.
xargs -n 1 find -name
Обработка имен файлов с пробелами
В начале данной статьи было сказано, что xargs воспринимает пробелы (а также символы новой строки) как разделители. В случае, если передаваемые имена файлов содержат пробелы, это может вызвать проблемы.
Например, в текущей директории есть файл с именем ‘new music.mp3’. И требуется передать его проигрывателю mplayer, чтобы воспроизвести музыку. Если указать его обычным способом, это вызовет ошибку:
Она возникает из-за пробела между ‘new’ и ‘music.mp3’, из-за которого эти части имени воспринимаются проигрывателем как два разных файла. Один из способов решения этой проблемы — ввести перед пробелом обратный слэш:
new\ music.mp3
Однако, если ввод осуществляется не из стандартного потока ввода, это может быть неудобным. Поэтому есть и другой способ — изменить разделитель при помощи опции -d:
xargs -d '\n' mplayer
Данная команда будет воспринимать в качестве разделителя только символ новой строки.
Получение входных данных из файла
В рассмотренных выше примерах мы получали входные данные из стандартного потока ввода (по умолчанию) или от другой команды. Однако, при необходимости источником входных данных для xargs может быть файл.
Для этого используется опция -a. После которой нужно указать имя файла, используемого xargs в качестве источника входных данных.
Допустим, есть файл ‘input.txt’, содержащий входные данные для xargs (в нашем случае это имя двух директорий: /tmp и /mnt). Ниже приведен пример, как команда xargs может считать данные из этого файла и передать их другой команде, в данном случае ls:
xargs -a input.txt ls -lart
Результат выполнения команды:
Запрос разрешения пользователя перед выполнением команды
Мы уже рассмотрели, как обеспечить многократное выполнение команды. Но нам может потребоваться подтверждение пользователя при каждом запуске. Это можно сделать при помощи опции командной строки -p.
find *.txt | xargs -p rm -f
Как видим прежде чем удалить файлы команда запросила подтверждение
Заключение
Мы разобрали самые необходимые базовые функции команды xargs, необходимые для работы с этой полезной утилитой. Освоив принципы работы и функции команды, рассмотренные в данном руководстве, вы можете обратиться к соответствующей man-странице.