Por que o sinalizador "-or" para o GNU localiza a minha expressão para avaliar de uma maneira inesperada?

0

Os seguintes trabalhos funcionam como esperado:

[pitserver ~]% sudo find /home/pitserver/operator -uid 11 -exec ls -nld {} +
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28   32 Oct  3  2005 /home/pitserver/operator/.amandahosts
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

Espero que o seguinte liste todos os arquivos, mas ele lista todos os arquivos exceto .amandahosts :

[pitserver ~]% sudo find /home/pitserver/operator -name '.amandahosts' -or -uid 11 -exec ls -nld {} +        
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

Por que isso acontece?

    
por jayhendren 09.02.2015 / 19:37

1 resposta

1

De acordo com man find , a justaposição (que é um operador "e" implícito) tem precedência sobre o -or operator, então pode-se esperar que os argumentos sejam avaliados da seguinte forma:

( -name '.amandahosts' -or -uid 11 ) e ( -exec ls -ld {} + )

De fato, se eu adicionar os parentes ao comando find, ele funcionará como esperado:

[pitserver ~]% sudo find /home/pitserver/operator '(' -name '.amandahosts' -or -uid 11 ')' -exec ls -nld {} +
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28   32 Oct  3  2005 /home/pitserver/operator/.amandahosts
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

No entanto, encontrar realmente interpreta os argumentos como este:

( -name '.amandahosts' ) ou ( -uid 11 -exec ls -ld {} + )

Como você pode ver aqui:

[pitserver ~]% sudo find /home/pitserver/operator -name '.amandahosts' -or '(' -uid 11 -exec ls -nld {} + ')'
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

O que está acontecendo aqui é que o "ou" está em curto-circuito. A segunda parte do '-ou' ( -uid 11 -exec ls -ld {} + ) é avaliada somente se a primeira parte ( -name '.amandahosts' ) for avaliada como false . Portanto, o arquivo somente será executado -exec ... se o arquivo não for denominado '.amandahosts' . Uma maneira de ver como isso funciona é observar que os itens a seguir são bem-sucedidos:

[pitserver ~]% sudo find /home/pitserver/operator -name '.amandahosts' -exec ls -nld {} + -or -uid 11 -exec ls -nld {} +
-rw------- 1 11 28 32 Oct  3  2005 /home/pitserver/operator/.amandahosts
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

A melhor maneira de resolver esse problema parece ser usar sempre parens ao usar um operador "ou", pois isso fornece exatamente o comportamento desejado:

'(' -name '.amandahosts' -or -uid 11 ')' -exec ls -nld {} +

    
por 09.02.2015 / 19:37

Tags