`find` con più` -name` e `-exec` esegue solo le ultime corrispondenze di` -name`


74

Quando sto usando

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

trova tutti i tipi di file. Ma quando aggiungo -execalla fine:

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

sembra che stampa solo .txtfile. Che cosa sto facendo di sbagliato?

Nota: usando MINGW (Git Bash)


Suggerimento: il primo comando stampa anche le directory i cui nomi corrispondono *.js*o *.txt.
Carattere jolly

Risposte:


98
trova . -type f -name "* .htm *" -o -name "* .js *" -o -name "* .txt"

è l'abbreviazione di:

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

Cioè, poiché non viene specificato alcun predicato di azione (solo condizioni ), -printviene aggiunta implicitamente un'azione per i file che soddisfano le condizioni.

(e, a proposito, che stamperebbe .jsfile non regolari (l' -type funico vale per i .htmfile)).

Mentre:

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

è l'abbreviazione di:

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

Per find(come in molte lingue), AND ( -a; implicito quando omesso) ha la precedenza su OR ( -o) e l'aggiunta di un predicato di azione esplicita (qui -exec) annulla l' -printazione implicita vista sopra. Qui vuoi:

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

O:

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

Per evitare di eseguirne uno shper file.


In alcuni di quegli usi di sh -c, è necessario aggiungere l'argomento zeroth per sh (anche se in altri l'hai già incluso).
James Youngman,

1
Questa è un'ottima risposta!
Marinos il

30

Sono le parentesi implicite. Aggiungi parentesi esplicite.\( \)

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

o usando xargs (mi piacciono gli xargs lo trovo più facile, ma apparentemente non portatile).

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -print0 | xargs -0 -n1 echo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.