Как работает эта команда find с использованием «find ... -exec sh -c '...' sh {} +»?

Как работает эта команда find с использованием «find ... -exec sh -c '...' sh {} +»?

@StephaneChazelas опубликовал следующее решение этого вопроса и ответа:Возникли некоторые проблемы с использованием «find -exec {} +».

$ find . -iname "*.extension" -exec sh -c '
  exec <command> "$@" <additional parameters>' sh {} +

Что именно здесь происходит? Что конкретно делает последний sh {}? Кажется, он нужен только для того, чтобы успокоить -execкоманду find, чтобы она могла что-то делать, NOOP.

Я мог бы так же легко echo {}это сделать, и, похоже, все будет работать нормально.

решение1

Синтаксис следующий:

find ... -exec cmd {} +

findнайдет несколько файлов на основе критериев, указанных в, ...и запустит их cmdс этим списком путей к файлам в качестве аргументов, насколько это возможно, не превышая при этом ограничение на размер аргументов команды.

При необходимости он может разделить список файлов и вызвать cmdнесколько раз. Например, он может вызвать:

cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321

Ограничение в том, что это {}должно быть последним. Например, вы не можете написать:

find ... -exec cmd {} other args +

как вы могли бы ';'вместо '+'.

Ты можешь написать:

find ... -exec echo foo {} +

но нет:

find ... -exec echo {} foo +

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

В sh -c 'inline-script' x a b c, для inline-script, $0есть x, $1есть a, $2есть b... так же "$@"есть список этих 3 аргументов: a, b и c. Так что в:

find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +

Длявстроенный скрипт, $0(который используется, например, при отображении сообщений об ошибках) имеет значение find-shи "$@"представляет собой список файлов (то, во что он findрасширяется {}).

Используя execспециальную встроенную функцию оболочки:

find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +

Мы говорим оболочке не запускать дополнительный процесс для запуска cmd, а вместо этого запустить его в том же процессе (заменяя запущенный процесс оболочки этой командой). Некоторые оболочки, такие как zshи некоторые реализации kshделают это неявно для последней команды во встроенном скрипте (также bashкогда во встроенном скрипте только одна команда, как здесь).

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