Intereting Posts
Разветвление безопасности использования этой строки в visudo: yourUSERname ALL = (otherUSERaccount) NOPASSWD: ALL Почему мой Linux-сервер зависает с "ps aux" Как получить разбивку сегментации, работающую с systemd-networkd? Почему OOM-killer не регистрирует данные, чтобы быть видимыми через dmesg? Соответствие последовательному порядку Извлечь определенные слова из объекта Rsyslog% msg% Как захватить IP-адрес клиентов на мой сервер через обратный туннель ssh. Не удалось загрузить виртуальную машину: Ошибка 13: Неверный или неподдерживаемый исполняемый формат Как выполнить операцию по отдельным матчам в полной строке Проблема драйвера Nvidia на приостановление Linux Mint xrandr scale 2×2 для мультидисплея (4K HiDPI и Full HD mix) – размытый вывод Как я могу запускать сценарии командной оболочки Linux, которым нужна привилегия root с веб-страницы Принуждение X для распознавания видеопамяти, сохранение файла 99-vesa Где я могу найти, какие пакеты находятся на каждом компакт-диске Debian Squeeze? Визуально отображать раскладки клавиатуры X.org? / Также: откуда взялись раскладки клавиатуры X.org?

Когда требуется xargs?

Команда xargs всегда меня смущает. Есть ли общее правило, которое может помочь мне разобраться, когда мне это нужно?

Рассмотрим два примера ниже:

 $ \ls | grep Cases | less 

печатает файлы, соответствующие «Cases», но для изменения команды на touch потребуются xargs :

 $ \ls | grep Cases | touch touch: missing file operand Try `touch --help' for more information. $ \ls | grep Cases | xargs touch 

Разница заключается в том, какие данные принимает целевая программа.

Если вы просто используете канал, он получает данные на STDIN (стандартный поток ввода) в виде сырой груды данных, которые он может сортировать по одной строке за раз. Однако некоторые программы не принимают свои команды по стандарту, они ожидают, что это будет указано в аргументах команды. Например, touch принимает имя файла в качестве параметра в командной строке следующим образом: touch file1.txt .

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

Эти две вещи эквивалентны:

 # touch file1.txt # echo file1.txt | xargs touch 

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

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

Например:

 $ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8 

будет кодировать * .wav => * .flac, используя сразу три процесса ( -P 3 ).

xargs особенно полезен, когда у вас есть список файловых путей на stdin и вы хотите что-то с ними делать. Например:

 $ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g" 

Давайте рассмотрим это шаг за шагом:

 $ git ls-files "*.tex" tex/ch1/intro.tex tex/ch1/motivation.tex .... 

Другими словами, наш вход – это список путей, к которым мы хотим что-то сделать.

Чтобы узнать, что делает xargs с этими путями, хороший трюк заключается в том, чтобы добавить echo перед вашей командой, например:

 $ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g" sed -i "s/color/colour/g" tex/ch1/intro.tex sed -i "s/color/colour/g" tex/ch1/motivation.tex .... 

Аргумент -n 1 заставит xargs превратить каждую строку в собственную команду. Команда sed -i "s/color/colour/g" заменит все вхождения color colour для указанного файла.

Обратите внимание, что это работает только в том случае, если у вас нет пробелов в ваших путях. Если вы это сделаете, вы должны использовать пути с нулевым завершением в качестве входных данных для xargs, передав флаг -0 . Пример использования:

 $ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g" 

Что делает то же, что мы описали выше, но также работает, если один из путей имеет в нем пробел.

Это работает с любой командой, которая производит имена файлов как выходные данные, такие как find или locate . Если вы действительно используете его в репозитории git с большим количеством файлов, возможно, более эффективно использовать его с git grep -l вместо git ls-files , например:

 $ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g" 

Команда git grep -l "color" "*.tex" предоставит список файлов «* .tex», содержащих фразу «color».

Ваш первый аргумент хорошо иллюстрирует разницу.

\ls | grep Cases | less \ls | grep Cases | less позволяет просматривать список имен файлов, созданных ls и grep . Не имеет значения, что они являются именами файлов, это всего лишь текст.

\ls | grep Cases | xargs less \ls | grep Cases | xargs less позволяет просматривать файлы, имена которых создаются первой частью команды. xargs принимает список имен файлов в качестве ввода и команду в своей командной строке и запускает команду с именами файлов в командной строке.

xargs , что если использовать xargs , имейте в виду, что он ожидает, что ввод будет отформатирован странным образом: с разделителями пробелов, с \ , ' и ' используемым для цитирования (необычным способом, поскольку \ не является специальным внутри кавычек). Используйте только xargs если ваши имена файлов не содержат пробелов или \'" .

В вашем примере вам вообще не нужно использовать xargs так как find будет точно и безопасно делать то, что вы хотите сделать.

Именно то, что вы хотите использовать find :

 find -maxdepth 1 -name '*Cases*' -exec touch {} + 

В этом примере -maxdepth 1 означает только поиск в текущем каталоге, не спускайтесь в какие-либо подкаталоги; по умолчанию find будет выглядеть во всех подкаталогах (что часто бывает так, как вы хотите), если вы не ограничиваете его с помощью maxdepth. {} – это имя файла, который будет заменен на своем месте, а символ + – один из двух маркеров конца команды, а другой – ; , Разница между ними такова ; означает выполнение команды по каждому файлу по одному за раз, тогда как + означает выполнение команды во всех файлах одновременно. Обратите внимание, однако, что ваша оболочка, вероятно, попытается интерпретировать ; сам, поэтому вам нужно будет сбежать от него с помощью \; или ';' , Да, find есть несколько небольших неприятностей, подобных этому, но его сила более чем компенсирует это.

И find и xargs сложны, чтобы учиться сначала. Чтобы помочь вам изучить xargs попробуйте использовать опцию -p или --interactive которая покажет вам команду, которую она собирается выполнить, и предложит вам, хотите ли вы ее запустить.

Аналогично find вы можете использовать -ok вместо -exec чтобы -ok хотите ли вы выполнить команду.

Бывают моменты, когда find не сможет делать все, что вам нужно, и это то, где происходит xargs . Команда -exec будет принимать только один экземпляр {} , поэтому, если вы получите ошибку при find -type f -exec cp {} {}.bak \; поэтому вы можете сделать это так: find -type f -print0 | xargs -0 -l1 -IX cp X X.bak find -type f -print0 | xargs -0 -l1 -IX cp X X.bak

Вы можете узнать больше о командах запуска в руководстве GNU Findutils .

Кроме того, я упомянул, что find безопасно делает то, что вы хотите, потому что когда вы имеете дело с файлами, вы столкнетесь с пробелами и другими символами, которые вызовут проблемы с xargs если вы не используете параметр -0 или --null вместе с чем-то, что генерирует входные данные элементы, завершаемые нулевым символом, а не пробелы.

xargs (наряду с find , sort , du , uniq , perl и некоторыми другими) принимает ключ командной строки, чтобы сказать: «STDIN имеет список файлов, разделенных байтом NUL (0x00)». Это упрощает обработку имен файлов с пробелами и другими забавными символами. Имена файлов не содержат NUL.