'find' com múltiplos '-name' e '-exec' executa apenas as últimas correspondências de '-name'

56

Quando estou usando

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt"

encontra todos os tipos de arquivo. Mas quando eu adiciono -exec no final:

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt" -exec sh -c 'echo "$0"' {} \;

parece que só imprime .txt arquivos. O que estou fazendo errado?

Nota: usando o MINGW (Git Bash)

    
por jakub.g 22.11.2013 / 11:52

2 respostas

80
find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt"

é a abreviação de:

find . \( \( -type f -a -name "*.htm*" \) -o \
          \( -name "*.js*" \) -o \
          \( -name "*.txt" \) \
       \) -a -print

Isto é, porque nenhum predicado action é especificado (apenas condições ), uma ação -print é implicitamente adicionada para os arquivos que correspondem às condições.

(e, a propósito, que imprime arquivos .js não regulares (o -type f se aplica somente a arquivos .htm )).

Enquanto:

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \
  -exec sh -c 'echo "$0"' {} \;

é a abreviação de:

find . \( -type f -a -name "*.htm*" \) -o \
       \( -name "*.js*" \) -o \
       \( -name "*.txt" -a -exec sh -c 'echo "$0"' {} \; \)

Para find (como em vários idiomas), AND ( -a ; implícito quando omitido) tem precedência sobre OR ( -o ) e adição um predicado de ação explícito (aqui -exec ) cancela a ação implícita -print vista acima. Aqui você quer:

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) \
  -exec sh -c 'echo "$0"' {} \;

Ou:

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c '
   for i do
     echo "$i"
   done' sh {} +

Para evitar a execução de um sh por arquivo.

    
por 22.11.2013 / 13:34
22

São os colchetes implícitos. Adicione colchetes explícitos. \( \)

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c 'echo "$0"' {} \;

ou usando xargs (eu gosto de xargs eu acho mais fácil, mas aparentemente não é tão portátil).

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -print0 | xargs -0 -n1 echo
    
por 22.11.2013 / 12:31

Tags