find -exec + против find | xargs: что выбрать?

find -exec + против find | xargs: что выбрать?

Я понимаю, что -execможет принять +вариант, имитирующий поведение xargs. Есть ли ситуация, когда вы бы предпочли одну форму другой?

Лично я предпочитаю первую форму, хотя бы для того, чтобы избежать использования пайпа. Я думаю, что разработчики наверняка findсделали соответствующие оптимизации. Я прав?

решение1

Безопасная передача имен файлов по конвейеру xargsтребует, чтобы ваш findподдерживал эту -print0опцию и xargsимел соответствующую опцию для ее чтения ( --nullили -0). В противном случае имена файлов с непечатаемыми символами или обратными косыми чертами, кавычками или пробелами в имени могут вызвать неожиданное поведение. С другой стороны, find -exec {} +находится вfindСпецификация POSIX, поэтому он портативен, и он примерно такой же безопасный, как find -print0 | xargs -0, и определенно безопаснее, чем find | xargs. Я бы рекомендовалникогдаобходиться find | xargsбез -print0.

решение2

Вы можете захотеть сцепить вызовы find (когда-то, когда вы узнали, что это возможно, что может быть и сегодня). Конечно, это возможно только до тех пор, пока вы остаетесь в find. Как только вы передаете 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 или другой программы, чтобы передать обе строки как условие, но это не суть. Любая программа, которая может возвращать true или false, учитывая файл как аргумент, может быть использована здесь - grep был просто популярным примером.

И заметьте, вы можете следоватьнайти -execс другими командами поиска, такими как-лсили-удалитьили что-то подобное. Обратите внимание, что delete делает не только rm (удаляет файлы), но и rmdir (удаляет каталоги).

Такая цепочка читается как комбинация команд И, если не указано иное (а именно, с переключателем -or(и скобками (которые необходимо маскировать))).

Так что вы не покидаете цепочку поиска, что удобно. Я не вижу никаких преимуществ в использовании -xargs, поскольку вам нужно быть осторожным при передаче файлов, а find этого делать не нужно — он автоматически обрабатывает передачу каждого файла как одного аргумента для вас.

Если вы считаете, что вам нужна маскировка находок{} фигурные скобки, не стесняйтесь посетить мой вопрос, который требует доказательств. Мое утверждение: Вы не делаете.

решение3

Если вы используете -exec ... ;форму (не забывая экранировать точку с запятой), вы запускаете команду один раз для каждого имени файла. Если вы используете -print0 | xargs -0, вы запускаете несколько команд для каждого имени файла. Вам определенно следует использовать -exec +форму, которая помещает несколько файлов в одну командную строку и работает намного быстрее, когда задействовано большое количество файлов.

Большим плюсом использования xargsявляется возможность параллельного запуска нескольких команд с помощью xargs -P. На многоядерных системах это может обеспечить огромную экономию времени.

решение4

Что касается производительности, я думал, что это -exec … +будет просто лучше, потому что это один инструмент, выполняющий всю работу, ночасть документации GNU findutilговорит, что -exec … +в некоторых случаях это может быть менее эффективно:

[найти с -exec … +]может быть менее эффективным, чем некоторые применения xargs; например, xargsпозволяет создавать новые командные строки, пока предыдущая команда все еще выполняется, и позволяет вам указать несколько команд для параллельного выполнения. Однако конструкция find ... -exec ... +имеет преимущество широкой переносимости. GNU findutils не поддерживал ' -exec ... +' до версии 4.2.12[Январь 2005]; одной из причин этого является то, что -print0в любом случае уже имело место действие ' '.

Я не был уверен, что это значит, поэтому спросил в чате, гдедеробертобъяснил это так:

findвероятно, можно было бы продолжить поиск следующей партии файлов во время -exec … +работы, но он этого не делает,
find … | xargs …потому что тогда поиск — это другой процесс, и он продолжает работать до тех пор, пока буфер канала не заполнится

(Форматирование мое.)

Вот так. Но если производительность действительно имеет значение, вам придется провести реалистичное тестирование или даже спросить себя, стоит ли вам вообще использовать оболочку в таких случаях.

Я думаю, что здесь, на этом сайте, лучше посоветовать людям использовать эту -exec … +форму, когда это возможно, просто потому, что это проще, и по причинам, упомянутым в других ответах здесь (например, обработка странных имен файлов без необходимости много думать).

Связанный контент