Я знаю grep
команда и я узнаем о технических возможностях xargs
, таким образом, я прочитал эту страницу, которая дает некоторые примеры того, как использовать xargs
команда.
Я смущен последним примером, пример 10. Это говорит, что "Команда xargs выполняет команду grep для нахождения всех файлов (среди файлов, обеспеченных командой находки), который содержал строку ‘stdlib.h’"
$ find . -name '*.c' | xargs grep 'stdlib.h'
./tgsthreads.c:#include
./valgrind.c:#include
./direntry.c:#include
./xvirus.c:#include
./temp.c:#include
...
...
...
Однако, что различие к простому использованию
$ find . -name '*.c' | grep 'stdlib.h'
?
Очевидно, я все еще борюсь с тем, что точно делает xargs, таким образом, любая справка ценится!
$ find . -name '*.c' | grep 'stdlib.h'
Это передает вывод по каналу (stdout) * от find
к (stdin) * grep 'stdlib.h'
как текст (т.е. имена файлов рассматриваются как текст). grep
делает его обычную вещь и находит согласующие отрезки длинной линии в этом тексте (любые имена файлов, которые сами содержат шаблон). Содержание файлов никогда не читается.
$ find . -name '*.c' | xargs grep 'stdlib.h'
Это создает команду grep 'stdlib.h'
к которому каждый результат find
аргумент - таким образом, это будет искать соответствия в каждом файле, найденном find
(xargs
может считаться превращением его stdin в аргументы данным командам), *
Использовать -type f
в Вашей команде находки, или Вы получите ошибки от grep
для соответствия каталогам. Кроме того, если имена файлов имеют пробелы, xargs
завинтит плохо, так используйте пустой разделитель путем добавления -print0
и xargs -0
для более надежных результатов:
find . -type f -name '*.c' -print0 | xargs -0 grep 'stdlib.h'
*добавили эти дополнительные объяснительные точки, как предложено в комментарии @cat
xargs
привык к автоматическому, генерируют параметры командной строки, базирующиеся (обычно) на списке файлов.
Настолько рассматривающий некоторые альтернативы использованию команды followoing xargs
:
find . -name '*.c' -print0 | xargs -0 grep 'stdlib.h'
существует несколько причин использовать его вместо других опций, которые не были первоначально упомянуты в других ответах:
find . -name '*.c' -exec grep 'stdlib.h' {}\;
генерирует один grep
процесс для каждого file—, это обычно считают плохой практикой и может создать большую нагрузку для системы, если существует много найденных файлов. grep 'stdlib.h' $(find . -name '*.c')
, команда, вероятно, перестанет работать, потому что вывод $(...)
операция превысит максимальную длину командной строки оболочки , Как упомянуто в других ответах, причине использования -print0
аргумент find
в этом сценарии и -0
аргумент xargs, то, так, чтобы имена файлов с определенными символами (например, кавычки, пробелы или даже новые строки) были все еще обработаны правильно.
xargs берет свой стандартный вход и превращает его в командную строку args.
find . -name '*.c' | xargs grep 'stdlib.h'
очень похоже на
grep 'stdlib.h' $(find . -name '*.c') # UNSAFE, DON'T USE
И даст те же результаты, пока список имен файлов не является слишком длинным для единственной командной строки. (Linux поддерживает мегабайты текста на единственной командной строке, так обычно Вам не нужен xargs.)
Но оба из них сосут, потому что они повреждаются, если Ваши имена файлов содержат пробелы. Вместо этого find -print0 | xargs -0
работы, но так делает
find . -name '*.c' -exec grep 'stdlib.h' {} +
Это никогда не передает имена файлов по каналу нигде: find
обрабатывает их в пакетном режиме в большую командную строку и выполнения grep
непосредственно.
\;
вместо +
выполнения grep отдельно для каждого файла, который намного медленнее. Не делайте этого. Но +
расширение GNU, таким образом, Вам нужно xargs
чтобы сделать это эффективно, если Вы не можете принять, GNU находит.
Если Вы не учитываете xargs
, find | grep
делает его сопоставление с образцом против списка имен файлов это find
печать.
Таким образом в той точке, Вы могли бы также просто сделать find -name stdlib.h
. Конечно, с -name '*.c' -name stdlib.h
, Вы не получите вывода, потому что те шаблоны не могут и соответствовать, и поведение находки по умолчанию к И правила вместе.
Замена less
в любой точке в процессе для наблюдения то, что производит любую часть конвейера, производит.
Дальнейшее чтение: http://mywiki.wooledge.org/BashFAQ имеет некоторый большой материал.
В целом, xargs
используется для случаев, где Вы передали бы по каналу (с символом |
) что-то от одной команды до другого (Command1 | Command2
), но вывод от первой команды правильно не получен как вход для второй команды.
Это обычно происходит, когда вторая команда не обрабатывает ввод данных через Стандарт В (stdin) правильно (например: Несколько строк, как введено, путь строки являются установкой, символы, используемые в качестве входа, несколько параметров, как введено, тип данных, полученный, как введено, и т.д.). Чтобы дать Вам быстрый пример, протестируйте следующее:
Пример 1:
ls | echo
- Это ничего не сделает с тех пор echo
не знает, как обработать вход, который он получает. Теперь в этом случае, если мы используем xargs
это обработает вход способом, который может быть обработан правильно echo
(например: Как одна строка информации)
ls | xargs echo
- Это произведет всю информацию от ls
в одной строке
Пример 2:
Скажем, у меня есть несколько goLang файлов в названной папке, идут. Я искал бы их с чем-то вроде этого:
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
.