Quando irá 'encontrar. -exec COMMAND {} + 'executa o comando várias vezes?

8

Se eu fizer

find . -exec echo {} +

imprime todos os caminhos em uma linha, ou seja, o comando echo é executado apenas uma vez.

Mas de acordo com man find ,

-exec command {} +
    ... the number of invocations of the command will 
be much  less  than  the  number  of matched files. ...

Parece que, em algumas circunstâncias, o comando será executado várias vezes. Estou certo? Por favor, exemplifique.

    
por frozen-flame 29.08.2014 / 05:09

2 respostas

7

POSIX definido find -exec utility_name [argumento ...] {} + como:

The end of the primary expression shall be punctuated by a <semicolon> or by a <plus-sign>. Only a <plus-sign> that immediately follows an argument containing only the two characters "{}" shall punctuate the end of the primary expression. Other uses of the <plus-sign> shall not be treated as special. If the primary expression is punctuated by a <semicolon>, the utility utility_name shall be invoked once for each pathname and the primary shall evaluate as true if the utility returns a zero value as exit status. A utility_name or argument containing only the two characters "{}" shall be replaced by the current pathname. If a utility_name or argument string contains the two characters "{}", but not just the two characters "{}", it is implementation-defined whether find replaces those two characters or uses the string without change.

If the primary expression is punctuated by a <plus-sign>, the primary shall always evaluate as true, and the pathnames for which the primary is evaluated shall be aggregated into sets. The utility utility_name shall be invoked once for each set of aggregated pathnames. Each invocation shall begin after the last pathname in the set is aggregated, and shall be completed before the find utility exits and before the first pathname in the next set (if any) is aggregated for this primary, but it is otherwise unspecified whether the invocation occurs before, during, or after the evaluations of other primaries. If any invocation returns a non-zero value as exit status, the find utility shall return a non-zero exit status. An argument containing only the two characters "{}" shall be replaced by the set of aggregated pathnames, with each pathname passed as a separate argument to the invoked utility in the same order that it was aggregated. The size of any set of two or more pathnames shall be limited such that execution of the utility does not cause the system's {ARG_MAX} limit to be exceeded. If more than one argument containing the two characters "{}" is present, the behavior is unspecified.

Quando o comprimento do conjunto de arquivos que você encontrou exceder o sistema ARG_MAX , o comando é executado.

Você pode obter ARG_MAX usando o getconf :

$ getconf ARG_MAX
2097152

Em alguns sistemas, o valor real de ARG_MAX pode ser diferente. Você pode consultar aqui para mais detalhes.

    
por 29.08.2014 / 06:35
7

Existe um tamanho máximo de lista de argumentos para um novo processo no sistema POSIX. find dividirá a execução se os caminhos dos arquivos forem maiores que isso. Para ver o limite no Linux, use xargs --show-limits (não funciona no Mac OS, se alguém souber uma alternativa melhor, por favor, comente aqui)

edit: roubado direto da resposta de Gnouc, a maneira POSIX de obter o tamanho máximo da lista de argumentos é getconf ARG_MAX . No entanto, eu executei uma experiência na minha máquina do mac e parece que find usa um pouco mais da metade desse número. Isso é coerente com o fato de que, no sistema em que funciona, xargs --show-limits nos diz que não estará usando o comprimento máximo do argumento (nesse caso também usará cerca de metade desse número), mas não encontrar uma explicação para isso.

edit 2: parece que a única forma confiável de determinar quantos parâmetros find irão unir para cada chamada é experimentar, por exemplo, executando

find / -exec echo {} + | wc -cl

Como a saída de find tem uma linha para cada invocação de echo , é possível contá-las usando wc -l . O número total de bytes echo ed é a saída de wc -c . Dividindo um pelo outro, você obtém o número médio de bytes nos parâmetros para cada chamada de comando (embora um valor ligeiramente inferior, por causa do arredondamento, aproximadamente metade do comprimento médio de um caminho em seu sistema)

    
por 29.08.2014 / 05:22

Tags