@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 -exec
o 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 {} +
find
encontrará um número de arquivos com base nos critérios ...
e executará cmd
com 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 cmd
vá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 cmd
apó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
, $0
is x
, $1
is a
, $2
is 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-sh
e "$@"
é a lista de arquivos (o que find
se expande {}
).
Usando o exec
recurso 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 zsh
e algumas implementações ksh
fazem isso implicitamente para o último comando em um script embutido (também bash
quando há apenas um comando no script embutido como aqui).