Что делает “ xargs grep ” делать?

Если вы установили GNOME (3.8) из стандартных репозиториев Ubuntu 13.10, перед обновлением нет необходимости удалять.

Если вы установили более последнюю версию GNOME 3.10 через PPP GNOME, вы должны сначала удалить его с помощью утилиты ppa-purge, следуя инструкциям в связанной статье. Это уменьшит пакеты GNOME до версий в официальном репозитории Ubuntu, чтобы обновление дистрибутива продолжалось плавно.

1
задан 5 October 2016 в 02:27

3 ответа

xargs принимает свой стандартный ввод и превращает его в аргументы командной строки.

find . -name '*.c' | xargs grep 'stdlib.h' очень похож на

grep 'stdlib.h' $(find . -name '*.c')  # UNSAFE, DON'T USE

И даст те же результаты, пока список имен файлов не слишком длинный для одной командной строки. (Linux поддерживает мегабайты текста в одной командной строке, поэтому обычно вам не нужны xargs.)

Но оба эти сосать, потому что xargs принимает свой стандарт input и превращает его в аргументы командной строки. . Вместо этого работает find -print0 | xargs -0, но также

find . -name '*.c' -exec grep 'stdlib.h' {} +

. Нигде нигде не сбивает имена файлов: find доставляет их в большую командную строку и запускает grep напрямую.

\; вместо + запускает grep отдельно для каждого файла, что намного медленнее. Не делай этого. Но + является расширением GNU, поэтому вам нужно xargs сделать это эффективно, если вы не можете принять GNU find.

Если вы не указали xargs, find | grep сопоставляет свой шаблон с списком имен файлов, которые find печатает.

Итак, в этот момент вы могли бы просто сделать find -name stdlib.h. Конечно, с -name '*.c' -name stdlib.h вы не получите никакого вывода, потому что эти шаблоны не могут совпадать, а поведение по умолчанию для поиска - это AND и вместе.

Замените less в любой точке процесс, чтобы увидеть, какой результат выдает какая-либо часть конвейера.

Дальнейшее чтение: http://mywiki.wooledge.org/BashFAQ имеет отличные вещи.

4
ответ дан 23 May 2018 в 05:29
  • 1
    GNU xargs также имеет -d для установки разделителя, поэтому вы можете использовать -d'\n' для обработки списка, разделенного новой строкой, что может быть полезно, если вы обрабатываете список имен файлов в файле и т. Д. (Если имена файлов в них не имеют новых строк, то есть.) – ilkkachu 5 October 2016 в 13:58
  • 2
    @ilkkachu: да, новые строки в именах файлов намного реже, чем пробелы, так как они разбивают большинство скриптов. myfunc(){ local IFS=$'\n'; fgrep stdlib.h` $ (find) ; } также работает с тем же эффектом. Или как однострочный, подселлем (IFS=...; cmd...) также работает, чтобы содержать изменение в IFS, не сохраняя / не восстанавливая его. – Peter Cordes 5 October 2016 в 15:35
  • 3
    @PeterCordes Пожалуйста, не делайте command $( find ) тип материала. Проблемные имена файлов с пробелами и специальными символами могут нарушить этот тип вещей. По крайней мере, двойная цитата - замена команды. – Sergiy Kolodyazhnyy 24 May 2017 в 01:31
  • 4
    @SergiyKolodyazhnyy: Спасибо, что указали, что похоже, что я действительно рекомендую это сделать. У людей, скиммингов, может быть скопировано / вставлено, что вместо чтения следующего раздела. Обновлено для решения этой проблемы. – Peter Cordes 24 May 2017 в 01:45
  • 5
    @ СергейКолодянный: Или вы ответили на мой комментарий? Обратите внимание, что я устанавливаю IFS, поэтому он эквивалентен использованию xargs '-d\n'. Расширение Glob и обработка метасимволов оболочки происходят до эффектов подстановки команды, поэтому я думаю, что это безопасно даже с именами файлов, которые содержат $() или >. Согласился, что использование разделения слов при подстановке команд не является хорошей практикой, кроме одноразового интерактивного использования, когда вы знаете что-то о именах файлов. Но command "$(find)" полезен только в том случае, если вы ожидаете получить ровно 1 имя файла ... – Peter Cordes 24 May 2017 в 01:53

В общем случае xargs используется для случаев, когда вы будете передавать (с символом |) что-то из одной команды в другую (Command1 | Command2), но вывод из первой команды неверно принят как вход для второй команды.

Это обычно происходит, когда вторая команда неправильно обрабатывает ввод данных через стандартный вход (stdin) (например: несколько строк в качестве входных данных, способ настройки линий, символы, используемые в качестве входных данных, несколько параметров как вход, тип данных, полученный как вход, и т. д.). Чтобы дать вам быстрый пример, проверьте следующее:

Пример 1:

ls | echo - Это ничего не будет делать, поскольку echo не знает, как обрабатывать входные данные принимается. Теперь в этом случае, если мы будем использовать xargs, он будет обрабатывать вход таким образом, который можно корректно обрабатывать с помощью echo (например: как одна строка информации)

ls | xargs echo - это будет выводит всю информацию из ls в одной строке

Пример 1:

Допустим, у меня есть несколько файлов goLang внутри папки с именем go. Я бы поискал их с чем-то вроде этого:

find go -name *.go -type f | echo - Но если там есть символ трубы и echo, это не сработает.

find go -name *.go -type f | xargs echo - Здесь это сработало бы благодаря xargs, но если бы я хотел, чтобы каждый ответ от команды find в одной строке, я бы сделал следующее:

find go -name *.go -type f | xargs -0 echo - В этом случае тот же вывод из find будет показан echo.

Команды, такие как cp, echo, rm, less и другие, которые нуждаются в лучшем способе обработки ввода, получают выгоду при использовании с xargs. [!d12 ]

3
ответ дан 23 May 2018 в 05:29

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

Существует несколько причин использовать его, о котором я еще не упоминал выше:

find . -name '*.c' -exec grep {}\; будет генерировать один процесс grep для каждого файла - это обычно считается плохой практикой и может наложить большую нагрузку на систему, если обнаружено много файлов. Если есть много файлов, команда grep 'stdlib.h' $(find . -name '*.c'), скорее всего, не сработает, потому что вывод операции $(...) превысит максимальную длину командной строки оболочки

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

0
ответ дан 23 May 2018 в 05:29

Другие вопросы по тегам:

Похожие вопросы: