Возможно, вы захотите связать вызовы, чтобы найти (однажды, когда вы узнали, что это возможно, что может быть сегодня). Это, конечно, возможно только до тех пор, пока вы остаетесь в поиске. Как только вы отправляете xargs по конвейеру, это выходит за рамки.
Небольшой пример, два файла a.lst и b.lst:
cat a.lst
fuddel.sh
fiddel.sh
cat b.lst
fuddel.sh
Здесь нет хитрости - просто тот факт, что оба содержат «fuddel», но только один содержит «fiddel».
Предположим, мы этого не знали. Мы ищем файл, который соответствует 2 условиям:
find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097 4 -rw-r--r-- 1 stefan stefan 20 Jun 27 17:05 ./a.lst
Ну, может быть, вы знаете синтаксис для grep или другой программы для передачи обеих строк как условия, но это не главное. Здесь можно использовать любую программу, которая может возвращать истину или ложь, учитывая файл в качестве аргумента - grep был просто популярным примером.
И обратите внимание, вы можете использовать команду find -exec с другими командами поиска, такими как -ls или -delete или что-то подобное. Обратите внимание, что delete не только делает rm (удаляет файлы), но и rmdir (удаляет каталоги).
Такая цепочка читается как комбинация команд AND, если не указано иное (а именно с -or
переключателем (и паренсом (которые требуют маскировки))).
Таким образом, вы не покидаете цепочку поиска, что очень удобно. Я не вижу никакого преимущества в использовании -xargs, так как вы должны быть осторожны при передаче файлов, а это то, что не нужно делать при поиске - он автоматически обрабатывает передачу каждого файла в качестве единственного аргумента для вас.
Если вы считаете, что вам нужна маскировка для фигурных скобок {} , не стесняйтесь посетить мой вопрос, который требует доказательств. Мое утверждение таково: нет.
find
. Большое спасибо!-exec
сделать,xargs -P4
чтобы три из четырех ядер не оставались без дела?Для безопасной передачи имен файлов
xargs
требуется, чтобы ваша опцияfind
поддерживала,-print0
а у васxargs
была соответствующая опция для ее чтения (--null
или-0
). В противном случае имена файлов с непечатаемыми символами, обратной косой чертой, кавычками или пробелами в имени могут вызвать непредвиденное поведение. С другой стороны, онfind -exec {} +
входит в спецификацию POSIXfind
, поэтому он переносим, и он примерно так же безопасен, какfind -print0 | xargs -0
и определенно безопаснее, чемfind | xargs
. Я рекомендовал бы никогда не делатьfind | xargs
без-print0
.источник
find … -exec … {} +
является OpenBSD, которая приобрела эту функцию только с версией 5.1, выпущенной в 2012 году. Все BSD работали в-print0
течение нескольких лет, даже OpenBSD (хотя она тоже некоторое время сопротивлялась этой функции). Солярис, с другой стороны, придерживается функций POSIX, так что вы получите,-exec +
и нет-print0
.-print0
это боль, и хотя вы можете утверждать, чтоxargs --delimiter "\n"
это не эквивалентно, я никогда не использовал первое после обнаружения последнего.-0
это больше боли, чем--delimiter "\n"
.-0
, GNUxargs
необходимо-r
избегать запуска команды, если нет ввода.| xargs -r0 cmd
заключается в том, чтоcmd
это влияет на stdin (в зависимости отxargs
реализации, это/dev/null
или канал.Если вы используете
-exec ... ;
форму (не обращая внимания на точку с запятой), вы запускаете команду один раз для каждого имени файла. Если вы используете-print0 | xargs -0
, вы запускаете несколько команд для имени файла. Вы обязательно должны использовать-exec +
форму, которая помещает несколько файлов в одну командную строку и намного быстрее, когда задействовано большое количество файлов.Большим плюсом использования
xargs
является возможность запускать несколько команд параллельноxargs -P
. В многоядерных системах это может значительно сэкономить время.источник
-P
вместо-p
. Имейте в видуxargs -P
, не в стандарте POSIX, аfind -exec {} +
есть, что важно, если вы собираетесь на переносимость.find /tmp/ -exec ls "{}" +
работает просто отлично.-exec
(я мазохист, я даже не использую кавычки{}
, я всегда печатаю\{\}
, не спрашиваю), все выглядит так, как будто его сейчас нужно экранировать.find /tmp/ -exec ls {} +
бы не работал.bash
начал дословно принимать скобки. Я почти уверен, что по крайней мере один из старых снарядов, которые я использовал, бросил шипучие приступы, если скобки не сбежали.Что касается производительности, я подумал, что
-exec … +
было бы лучше, потому что это единственный инструмент, выполняющий всю работу, но часть документации GNU findutil говорит, что-exec … +
в некоторых случаях это может быть менее эффективно:Я не был точно уверен, что это значит, поэтому я спросил в чате, где Дероберт объяснил это так:
(Форматирование мной.)
Так что это так. Но если производительность действительно имеет значение, вам придется провести реалистичный бенчмаркинг или даже спросить себя, хотите ли вы использовать оболочку для таких случаев.
Здесь, на этом сайте, я думаю, что лучше советовать людям использовать
-exec … +
форму всегда, когда это возможно, потому что это проще и по причинам, указанным в других ответах здесь (например, обработка странных имен файлов без необходимости много думать).источник