Como funciona esse comando find usando "find ... -exec sh -c '...' sh {} +"?

Como funciona esse comando find usando "find ... -exec sh -c '...' sh {} +"?

@StephaneChazelas postou a seguinte solução para estas perguntas e respostas:Tendo alguns problemas ao usar “find -exec {} +”.

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

O que exatamente está acontecendo aqui? Especificamente, o que o último sh {}faz? Parece que existe apenas para pacificar -execo comando find para que ele tenha algo a fazer, um NOOP.

Eu poderia facilmente colocar echo {}lá e parece funcionar muito bem.

Responder1

A sintaxe é:

find ... -exec cmd {} +

findencontrará um número de arquivos com base nos critérios ...e executará cmdcom essa lista de caminhos de arquivo como argumentos, tantos quanto possível, sem ultrapassar o limite do tamanho dos argumentos de um comando.

Se necessário, pode dividir a lista de arquivos e ligar cmdvárias vezes. Por exemplo, pode acabar chamando:

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

Uma limitação disso é que {}tem que ser o último. Você não pode, por exemplo, escrever:

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

como você poderia com ';'em vez de '+'.

Você pode escrever:

find ... -exec echo foo {} +

mas não:

find ... -exec echo {} foo +

Portanto, se você precisar adicionar alguns argumentos extras cmdapós a lista de arquivos, será necessário recorrer à chamada de um shell. (Outras razões pelas quais você precisaria chamar um shell seriam sempre que você precisasse usar um recurso de shell, como redirecionamentos, pipes, algumas expansões de string....)

Em sh -c 'inline-script' x a b c, para inline-script, $0is x, $1is a, $2is b... assim como "$@"a lista desses 3 argumentos: a, b e c. Então em:

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

Para oscript embutido, $0(que é usado, por exemplo, ao exibir mensagens de erro) é definido como find-she "$@"é a lista de arquivos (o que findse expande {}).

Usando o execrecurso interno especial do shell:

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

Dizemos ao shell para não bifurcar um processo extra para run cmd, mas, em vez disso, executá-lo no mesmo processo (substituindo o processo do shell em execução por esse comando). Alguns shells gostam zshe algumas implementações kshfazem isso implicitamente para o último comando em um script embutido (também bashquando há apenas um comando no script embutido como aqui).

informação relacionada