Como é que este comando find usando “find… -exec sh -c '…' sh {} +” funciona?

8

@StephaneChazelas postou a seguinte solução para este Q & A: Tendo alguns problemas usando “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 está apenas lá para pacificar o comando -exec do find, para que ele tenha algo a fazer, um NOOP.

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

    
por slm 02.10.2013 / 20:25

2 respostas

8

A sintaxe é:

find ... -exec cmd {} +

find encontrará vários arquivos com base nos critérios em ... e executará cmd com essa lista de caminhos de arquivos como argumentos, o maior número possível sem ultrapassar o limite do tamanho dos argumentos para um comando.

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

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

Uma limitação é 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 a cmd após a lista de arquivos, precisará recorrer a chamar um shell. (Outras razões pelas quais você precisaria chamar um shell seriam sempre que precisar usar um recurso de shell como redirecionamentos, pipes, algumas expansões de strings ....)

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

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

Para o script in-line , $0 (que é usado por exemplo ao exibir mensagens de erro) está definido como find-sh e "$@" é a lista de arquivos (que find expande {} para).

Usando o exec especial embutido no shell:

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

Dizemos ao shell para não bifurcar um processo extra para executar cmd , mas em vez disso executá-lo no mesmo processo (substituindo o processo do shell em execução por esse comando). Alguns shells como bash , zsh e algumas implementações de ksh fazem isso implicitamente para o último comando em um script.

    
por 02.10.2013 / 21:01
-2

sh {} Isso significa que executar o comando no shell e na entrada inteira significa exatamente a entrada de correspondência pelo comando find ...

    
por 02.10.2013 / 21:01