Поиск по сайту:

Как использовать команду xargs в Linux


Нужно объединить несколько команд Linux, но одна из них не принимает ввод по конвейеру? xargs может принимать выходные данные одной команды и отправлять их другой команде в качестве параметров.

Все стандартные утилиты Linux имеют три связанных с ними потока данных. Это стандартный поток ввода (stdin), стандартный поток вывода (stdout) и стандартный поток ошибок (stderr).

Эти потоки работают с текстом. Мы отправляем ввод (stdin) в команду с помощью текста, а ответ (stdout) записывается в окно терминала в виде текста. Сообщения об ошибках также записываются в окно терминала в виде текста (stderr).

Одной из замечательных особенностей Linux и Unix-подобных операционных систем является возможность направлять вывод stdout одной команды на ввод stdin второй команды. Первой команде все равно, что ее вывод не идет в окно терминала, а второй команде все равно, что ее ввод не идет с клавиатуры.

Хотя все команды Linux имеют три стандартных потока, не все они принимают стандартный вывод другой команды в качестве входных данных для своего стандартного ввода. Это означает, что вы не можете передать им входные данные.

xargs — это команда для построения конвейеров выполнения с использованием стандартных потоков данных. С помощью xargs мы можем сделать так, чтобы такие команды, как echo, rm и mkdir, принимали стандартный ввод в качестве аргументов.

Команда xargs

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

Мы можем использовать это, чтобы продемонстрировать, как xargs всегда будет генерировать одну строку вывода, даже из многострочного ввода.

Если мы используем параметр -1 (указать один файл в строке) с ls, мы получим один столбец имен файлов.

ls -1 ./*.sh

Здесь перечислены файлы сценариев оболочки в текущем каталоге.

Мы получаем один столбец, как и ожидалось. Если мы пропустим его через xargs, что мы получим?

ls -1 ./*.sh | xargs

Вывод записывается в окно терминала в виде одного длинного потока текста.

Именно эта возможность позволяет xargs передавать параметры другим командам.

Использование xargs с wc

Мы можем использовать xargs, чтобы wc легко подсчитывал слова, символы и строки в нескольких файлах.

ls *.page | xargs wc

Вот что происходит:

  • ls выводит список файлов *.page и передает этот список в xargs.
  • xargs передает имена файлов в wc.
  • wc обрабатывает имена файлов так, как если бы они были получены в качестве параметров командной строки.

Статистика для каждого файла отображается вместе с общим итогом.

Использование xargs с подтверждением

Мы можем использовать параметр -p (интерактивный), чтобы xargs запрашивал у нас подтверждение того, что мы согласны на его продолжение.

Если мы передадим строку имен файлов в touch через xargs, touch создаст файлы для нас.

echo 'one two three' | xargs -p touch

Отображается команда, которая будет выполнена, и xargs ждет, пока мы ответим, набрав «y» или «Y», или «n» или «N», и нажав Enter.

Если вы просто нажмете Enter, это будет обработано как «n». Команда выполняется, только если вы набираете «y» или «Y».

Мы нажали «y» и нажали Enter. Мы можем использовать ls, чтобы проверить, что файлы были созданы.

ls one two three

Использование xargs с несколькими командами

Мы можем использовать несколько команд с xargs с помощью параметра -I (начальные аргументы).

Этот параметр определяет «строку замены». Везде, где в командной строке появляется токен для строки замены, вставляются значения, предоставленные для xargs.

Давайте воспользуемся командой tree для просмотра подкаталогов из текущего каталога. Параметр -d (каталог) заставляет tree игнорировать файлы и сообщать только о каталогах.

tree -d

Существует единственный подкаталог под названием «images».

В файле с именем «directories.txt» у нас есть имена некоторых каталогов, которые мы хотим создать. Мы можем просмотреть его содержимое с помощью cat.

cat directories.txt

Мы собираемся использовать это как входные данные для xargs. Команда, которую мы собираемся выполнить, такова:

cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'

Это ломается следующим образом:

  • cat directory.txt |: содержимое файла directorys.txt (все новые имена каталогов) помещается в xargs.
  • xargs -I %: определяет «заменить строку» токеном «%».
  • sh -c: запускает новую подоболочку. -c (команда) указывает оболочке читать команды из командной строки.
  • ‘эхо %; mkdir %’: каждый из токенов «%» будет заменен именами каталогов, переданными с помощью  xargs. Команда echo напечатает имя каталога; команда mkdir создаст каталог.

Каталоги перечислены один за другим.

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

tree -d

Копирование файлов в несколько мест

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

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

В данном случае это команда cp. Таким образом, эффект заключается в вызове cp дважды, каждый раз с одним из двух каталогов в качестве параметра командной строки. Параметр xargs, который позволяет это сделать, — это опция -n (максимальное число). Мы собираемся установить это как один.

Мы также используем параметр -v (подробный) с cp, чтобы он сообщал о том, что происходит.

echo ~/Backups/ ~/Documents/page-files/ | xargs -n 1 cp -v ./*.page

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

Удаление файлов во вложенных каталогах

Если в именах файлов есть пробелы и странные символы, например символы новой строки, xargs не сможет их правильно интерпретировать. Мы можем решить эту проблему, используя опцию -0 (нулевой терминатор). Это говорит xargs использовать нулевой символ в качестве последнего разделителя для имен файлов.

В этом примере мы будем использовать find. find имеет собственный параметр для работы с пробелами и странными символами в именах файлов. Это опция -print0 (полное имя, нулевой символ).

find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"

Это ломается следующим образом:

  • найти . -name «*.png»: find будет искать в текущем каталоге «.» для объектов с именами, соответствующими «*.png», которые являются файлами (type -f).
  • -print0: имена будут заканчиваться нулевым символом, а пробелы и странные символы будут учитываться.
  • xargs -0: xargs также будет считать имена файлов заканчивающимися нулем, а пробелы и странные символы не вызовут проблем.
  • rm -v -rf “{}”: rm будет подробным и сообщит о том, что происходит (-v). Он будет рекурсивным (-r) и будет просматривать вложенные подкаталоги и удалять файлы без запроса (-f). «{}» заменяется каждым именем файла.

Поиск выполняется во всех подкаталогах, и файлы, соответствующие шаблону поиска, удаляются.

Удаление вложенных каталогов

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

tree -d
find . -name "level_one" -type d printo | xargs -o rm -v -rf "{}"

Эта команда будет использовать find для рекурсивного поиска в текущем каталоге. Целью поиска является каталог с именем «level_one». Имена каталогов передаются через xargs в rm.

Единственные существенные различия между этой командой и предыдущей командой заключаются в том, что термин поиска — это имя самого верхнего каталога, а -type d указывает find искать каталоги, а не файлы.

Имя каждого каталога печатается по мере его удаления. Мы можем проверить с помощью tree :

tree -d

Все вложенные подкаталоги удаляются.

Удаление всех файлов, кроме файлов одного типа

Мы можем использовать find, xargs и rm, чтобы удалить все файлы, кроме одного типа, который мы хотим сохранить. Это немного нелогично, но мы указываем имя типа файла, который хотим сохранить, а не имя файла, который хотим удалить.

Параметр -not сообщает find, чтобы он возвращал имена файлов, которые не соответствуют шаблону поиска. Мы снова используем параметр -I (начальные аргументы) с xargs. На этот раз токен замены строки, который мы определяем, — «{}». Это будет вести себя точно так же, как токен замены строки, который мы создали ранее, который оказался «%».

find . -type f -not - name "*.sh" -print0 | xargs -0 -I {} rm -v {}

Мы можем проверить с помощью ls. В каталоге остались только те файлы, которые соответствуют шаблону поиска «*.sh».

ls -l

Создание файла архива с помощью Xargs

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

Мы собираемся искать в текущем каталоге. Шаблон поиска — «*.page», поэтому мы будем искать файлы «.page».

find ./ - name "*.page" -type f -print0 | xargs -0 -tar -cvzf page_files.tar.gz

Файлы перечислены, как и ожидалось, поскольку файл архива создан.

Посредник данных

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

И xargs, и find имеют огромное количество параметров. Вам предлагается проверить их справочные страницы, чтобы узнать больше.

RELATED: Best Linux Laptops for Developers and Enthusiasts