`find` з декількома` -name` і `-exec` виконує лише останні збіги` -name`


74

Коли я використовую

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

він знаходить усі типи файлів. Але коли я додаю -execв кінці:

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

здається, він друкує лише .txtфайли. Що я роблю неправильно?

Примітка: використання MINGW (Git Bash)


Підказка: перша команда також буде друкувати каталоги , імена яких відповідають *.js*або *.txt.
Wildcard

Відповіді:


99
знайти. -тип f -name "* .htm *" -o -name "* .js *" -o -name "* .txt"

скорочено:

знайти. \ (\ ( -тип f -a- ім'я "* .htm *" \) -o \
          \ ( -name "* .js *" \) -o \
          \ ( -ім'я "* .txt" \) \
       \) -а -друк

Тобто, оскільки не вказаний предикат дії (лише умови ), -printдія неявно додається для файлів, які відповідають умовам.

(і, до речі, це друкувало б нестандартні .jsфайли ( -type fстосується лише .htmфайлів)).

Поки:

знайти. -тип f -name "* .htm *" -o -name "* .js *" -o -name "* .txt" \
  -exec sh -c 'echo "$ 0"' {} \;

скорочено:

знайти. \ ( -тип f -a -name "* .htm *" \) -o \
       \ ( -name "* .js *" \) -o \
       \ ( -name "* .txt" -a -exec sh -c 'echo "$ 0"' {} \; \)

Для find(як у багатьох мовах) AND ( -a; неявна, якщо пропущено) має перевагу над OR ( -o), а додавання явного предиката дії (тут -exec) скасовує -printнеявну дію, бачену вище. Тут ви хочете:

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

Або:

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

Щоб уникнути запуску одного shфайлу.


У деяких із цих можливостей sh -c вам потрібно додати нульовий аргумент для sh (хоча в інших ви вже включили його).
Джеймс Янгмен

1
Це чудова відповідь!
Марінос

30

Це думки, що маються на увазі. Додайте явні дужки.\( \)

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

або за допомогою xargs (мені подобаються xargs, мені це простіше, але, мабуть, не як портативно).

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -print0 | xargs -0 -n1 echo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.