Por que 'find -exec cmd {} +' precisa terminar em '{} +'?

11

Prefácio: Entendo a diferença entre -exec {} \;& -exec {} +. Eu também não tenho um problema como tal , estou apenas curioso sobre a semântica de find.


Ao finalizar o -execargumento com em +vez de ;, precisamos finalizar com {} +, por exemplo:

# FreeBSD find
$ find . -type f -exec cp {} /tmp +
find: -exec: no terminating ";" or "+"

# GNU find is even more cryptic:
$ find: missing argument to `-exec'

Usar ;esses exemplos em vez de +funcionar bem (mas obviamente faz outra coisa).

Do POSIX :

-exec utility_name [argument ...] ;
-exec utility_name [argument ...] {} +

... Somente um <plus-sign> que segue imediatamente um argumento contendo apenas os dois caracteres " {}" deve pontuar o final da expressão primária. Outros usos do <plus-sign> não devem ser tratados como especiais.

Em outras palavras, ao usar o +, o comando precisa terminar com {} +.

Por que é isso? E por que apenas com +e não o ;? No começo, pensei em talvez evitar conflitos com nomes de arquivos que contenham a +, mas nomes de arquivos com a ;parecem funcionar bem? Acho difícil acreditar que essa limitação é arbitrária ...

Martin Tournoij
fonte
3
FWIW, a página POSIX também diz que, The "-exec ... {} +" syntax adopted was a result of IEEE PASC Interpretation 1003.2 #210e nesse documento você encontrará mais detalhes, por exemplo:Note that the "+" is only treated as special if it immediately follows "{}". This minimises the chances of causing problems with existing uses of "+" as an argument with "-exec".
don_crissti 15/01/2015

Respostas:

5

A lógica dada na especificação POSIX é:

A "-exec ... {} +"sintaxe adotada foi resultado da Interpretação IEEE PASC 1003.2 # 210. Note-se que esta é uma alteração incompatível com a norma ISO / IEC 9899: 1999. Por exemplo, o comando a seguir imprime todos os arquivos com um '-'após o nome, se forem arquivos regulares, e um '+'caso contrário:

find / -type f -exec echo {} - ';' -o -exec echo {} + ';'

A alteração invalida o uso como este. Embora o padrão anterior tenha declarado que esse uso funcionaria, na prática muitos não o apoiavam e os desenvolvedores do padrão acharam melhor afirmar agora que isso não era permitido.

A Interpretação PASC 1003.2 # 210 entra em mais detalhes sobre a história de -exec … {} +. Ele existia em vários sistemas Unix antes de ser adotado pelo POSIX; o relatório de defeitos o rastreia de volta ao SVR4 (onde não havia documentos em grande parte). O relatório de defeitos justifica a alteração incompatível como tendo pouco impacto na prática:

Observe que o "+" é tratado apenas como especial se seguir imediatamente "{}". Isso minimiza as chances de causar problemas com os usos existentes de "+" como argumento com "-exec".

Embora a adição de suporte -exec … {} +interrompa alguns aplicativos em conformidade, como o exemplo acima, há menos deles do que se -exec … {} … +fosse permitido.

Outro motivo, talvez, para restringir {}o último argumento é a facilidade de implementação. Se {}fosse permitido em qualquer lugar da lista de argumentos -exec, o findprograma teria que criar a linha de comando copiando os argumentos estáticos, depois a parte variável e depois outra parte estática. Isso dificultaria a construção da lista de argumentos e a contabilização do limite de tamanho. A dificuldade é mínima, mas os implementadores gostam de cortar custos. O suporte a várias instâncias substituíveis de {}(se quiser -exec {} foo +funcionar, pode-se esperar logicamente que -exec {} foo {} +também) seria significativamente mais difícil.

Gilles 'SO- parar de ser mau'
fonte