Вам нужно связать несколько команд 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, чтобы легко подсчитать слова, символы и строки в нескольких файлах.
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 -d
Есть единственный подкаталог под названием «изображения».
В файле с именем «directoryies.txt» у нас есть имена некоторых каталогов, которые мы хотим создать. Мы можем посмотреть его содержимое с помощью cat.
cat directories.txt
Мы собираемся использовать это как входные данные для xargs. Мы собираемся использовать следующую команду:
cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'
Это выглядит так:
cat directoryies.txt |: это помещает содержимое файла directrories.txt (все новые имена каталогов) в xargs.
xargs -I%: определяет «заменяющую строку» с токеном «%».
sh -c: запускает новую подоболочку. -C (команда) указывает оболочке читать команды из командной строки.
‘echo%; 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 имеет свой собственный вариант для работа с пробелами и странные символы в именах файлов. Это опция -print0 (полное имя, нулевой символ).
find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"
Это выглядит так:
находить . -name «* .png»: find будет искать из текущего каталога «.» для объектов с именами, соответствующими «* .png», которые являются файлами (тип -f).
-print0: имена будут заканчиваться нулевым символом, а пробелы и странные символы будут учтены.
xargs -0: xargs также будет рассматривать имена файлов как завершающиеся нулем, а пробелы и странные символы не вызовут проблем.
rm -v -rf «{}»: rm будет подробным и сообщать о том, что происходит (-v). Он будет рекурсивным (-r), просматривать вложенные подкаталоги и удалять файлы без запроса (-f). «{}» Заменяется каждым именем файла.
Выполняется поиск во всех подкаталогах, а файлы, соответствующие шаблону поиска, удаляются.
Удаление вложенных каталогов
Допустим, мы хотим удалить набор вложенных подкаталогов. дерево позволит нам увидеть их.
tree -d
find . -name "level_one" -type d printo | xargs -o rm -v -rf "{}"
Эта команда будет использовать find для рекурсивного поиска в текущем каталоге. Целью поиска является каталог с именем «level_one». Имена каталогов передаются через xargs в rm.
Единственные существенные отличия между этой командой и предыдущей: поисковым запросом является имя самого верхнего каталога, а -type d указывает find искать каталоги, а не файлы.
Имя каждой директории печатается по мере ее удаления. Мы можем проверить с помощью дерева:
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 имеют огромное количество опций. Предлагаем вам ознакомиться с их справочными страницами, чтобы узнать больше.