Как исключить каталог в find.команда - PullRequest
1149 голосов
/ 18 ноября 2010

Я пытаюсь запустить команду find для всех файлов JavaScript, но как исключить конкретный каталог?

Вот код find, который мы используем.

for file in $(find . -name '*.js')
do 
  java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done

Ответы [ 33 ]

2 голосов
/ 18 марта 2015

Это подходит для меня на Mac:

find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune

Это исключит vendor и app/cache dir для имени поиска, к которому добавляется php.

2 голосов
/ 27 марта 2018

Для того, что мне было нужно, это работало так, находя landscape.jpg на всех серверах, начиная с root и исключая поиск в каталоге /var:

find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg

find / -maxdepth 1 -type d перечисляет все d каталогов в /

grep -v /var исключает `/ var 'из списка

xargs -I '{}' find '{}' -name landscape.jpg выполнить любую команду, например find, с каждым каталогом / результатом из списка

1 голос
/ 28 августа 2015

Лучше использовать действие exec, чем цикл for:

find . -path "./dirtoexclude" -prune \
    -o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;

exec ... '{}' ... '{}' \; будет выполняться один раз для каждого соответствующего файла, заменяя фигурные скобки '{}' текущим именем файла.

Обратите внимание, что скобки заключены в одинарные кавычки, чтобы защитить их от интерпретации как пунктуации сценария оболочки *.


Примечания

* Из раздела ПРИМЕРЫ справочной страницы find (GNU findutils) 4.4.2

1 голос
/ 26 января 2015

how-to-use-prune-option-find-in-sh - отличный ответ Лоуренса Гонсалвеса о том, как -prune работает.

И вот общее решение:

find /path/to/search                    \
  -type d                               \
    \( -path /path/to/search/exclude_me \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -prune                              \
  -o                                    \
  -type f -name '*\.js' -print

Чтобы избежать многократного ввода /path/to/seach/, оберните find в пару pushd .. popd.

pushd /path/to/search;                  \
find .                                  \
  -type d                               \
    \( -path ./exclude_me               \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -prune                              \
  -o                                    \
  -type f -name '*\.js' -print;         \
 popd
1 голос
/ 12 мая 2017

Я попробовал команду выше, но ни один из тех, кто использует "-prune", не работает для меня.В конце концов я попробовал это с командой ниже:

find . \( -name "*" \) -prune -a ! -name "directory"
1 голос
/ 27 сентября 2018

TLDR: понять ваши корневые каталоги и настроить поиск оттуда, используя опцию -path <excluded_path> -prune -o. Не включайте в конце исключенного пути трейлинг /.

Пример:

find / -path /mnt -prune -o -name "*libname-server-2.a*" -print


Чтобы эффективно использовать find, я считаю, что необходимо хорошо понимать структуру каталогов вашей файловой системы. На моем домашнем компьютере установлены жесткие диски с несколькими ТБ, резервная копия которых создается примерно для половины содержимого с использованием rsnapshot (т.е. rsync). Несмотря на то, что резервное копирование выполняется на физически независимый (дублирующий) диск, он монтируется в корневом системном каталоге (/): /mnt/Backups/rsnapshot_backups/:

/mnt/Backups/
└── rsnapshot_backups/
    ├── hourly.0/
    ├── hourly.1/
    ├── ...
    ├── daily.0/
    ├── daily.1/
    ├── ...
    ├── weekly.0/
    ├── weekly.1/
    ├── ...
    ├── monthly.0/
    ├── monthly.1/
    └── ...

Каталог /mnt/Backups/rsnapshot_backups/ в настоящее время занимает ~ 2,9 ТБ, с ~ 60M файлами и папками; простой просмотр этого содержимого требует времени:

## As sudo (#), to avoid numerous "Permission denied" warnings:

# date; echo; \
  time find /mnt/Backups/rsnapshot_backups | wc -l; echo; \
  time du /mnt/Backups/rsnapshot_backups -d 0; echo; \
  time rsnapshot du    ## << more accurate re: rsnapshot footprint

Wed 22 May 2019 10:37:14 AM PDT

34:07.30    ## 34 min
60314138    ## 60.3M files, folders

3112240160  /mnt/Backups/rsnapshot_backups    ## 3.1 TB
33:51.88    ## 34 min

2.9T    /mnt/Backups/rsnapshot_backups/hourly.0/
4.1G    /mnt/Backups/rsnapshot_backups/hourly.1/
...
4.7G    /mnt/Backups/rsnapshot_backups/weekly.3/
2.9T    total    ## 2.9 TB, per sudo rsnapshot du (more accurate)
2:34:54        ## 2 hr 35 min

Таким образом, в любое время, когда мне нужно найти файл в моем / (корневом) разделе, мне нужно иметь дело (избегать, если это возможно) с обходом моего раздела резервных копий.


Примеры

Среди подходов, по-разному предложенных в этой теме ( Как исключить каталог из команды find. Команда ), я считаю, что поиск с использованием принятого ответа на намного быстрее - с оговорками .

Решение 1

Допустим, я хочу найти системный файл libname-server-2.a, но я не хочу искать в моих rsnapshot резервных копиях. Чтобы быстро найти системный файл, используйте исключающий путь /mnt - , а не /mnt/ или /mnt/Backups, ...):

## As sudo (#), to avoid numerous "Permission denied" warnings:

# time find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
real    0m8.644s              ## 8.6 sec  <<< NOTE!
user    0m1.669s
 sys    0m2.466s

## As regular user (victoria), with alternate timing mechanism,
## as using 2?/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 3 sec     ## ~3 sec  <<< NOTE!

... находит этот файл всего за несколько секунд, в то время как это занимает много дольше (кажется, что рекурсивно проходит через все "исключенные" каталоги):

## As sudo (#), to avoid numerous "Permission denied" warnings:

# time find / -path /mnt/ -prune -o -name "*libname-server-2.a*" -print
find: warning: -path /mnt/ will not match anything because it ends with /.
/usr/lib/libname-server-2.a
real    33m10.658s            ## 33 min 11 sec (~231-663x slower!)
user    1m43.142s
 sys    2m22.666s

## As regular user (victoria), with alternate timing mechanism,
## as using 2?/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt/ -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 1775 sec    ## 29.6 min

Раствор 2

Другое решение, предлагаемое в этой теме ( SO # 4210042 ), также работает плохо:

## As sudo (#), to avoid numerous "Permission denied" warnings:

# time find / -name "*libname-server-2.a*" -not -path "/mnt"
/usr/lib/libname-server-2.a
real    33m37.911s            ## 33 min 38 sec (~235x slower)
user    1m45.134s
 sys    2m31.846s

# time find / -name "*libname-server-2.a*" -not -path "/mnt/*"
/usr/lib/libname-server-2.a
real    33m11.208s            ## 33 min 11 sec
user    1m22.185s
 sys    2m29.962s

Резюме

В «Решении 1» (... -path <excluded_path> -prune -o ...) кажется, что всякий раз, когда вы добавляете конечный /, команда затем рекурсивно вводит (все эти) /mnt/* каталоги - что в моем случае из-за /mnt/Backups/rsnapshot_backups/* Подкаталоги, дополнительно включает в себя ~ 2,9 ТБ файлов для поиска! Не добавляя завершающий /, поиск должен завершиться почти сразу (в течение нескольких секунд).

«Решение 2» (... -not -path <exclude path> ...) также, по-видимому, рекурсивно ищет в исключенных каталогах, не возвращая эти попадания, но излишне тратя это время поиска.


Поиск в этих rsnapshot резервных копиях:

Чтобы найти файл в одной из моих ежечасных / ежедневных / еженедельных / ежемесячных rsnapshot резервных копий):

$ START="$(date +"%s")" && find 2>/dev/null /mnt/Backups/rsnapshot_backups/daily.0 -name '*04t8ugijrlkj.jpg'; END="$(date +"%s")"; TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
find command took 312 sec   ## 5.2 minutes: despite apparent rsnapshot size
                            ## (~4 GB), it is in fact searching through ~2.9 TB)

Исключая вложенный каталог:

Здесь я хочу исключить вложенный каталог, например, /mnt/Vancouver/projects/ie/claws/data/* при поиске с /mnt/Vancouver/projects/:

$ time find . -iname '*test_file*'
./ie/claws/data/test_file
./ie/claws/test_file
0:01.97

$ time find . -path '*/data' -prune -o -iname '*test_file*' -print
./ie/claws/test_file
0:00.07

В сторону: Добавление -print в конце команды подавляет распечатку исключенного каталога:

$ find / -path /mnt -prune -o -name "*libname-server-2.a*"
/mnt
/usr/lib/libname-server-2.a

$ find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
1 голос
/ 22 апреля 2015

Я нашел имя функции в исходных файлах C исключая * .o и исключая * .swp и exclude (не обычный файл) и исключая вывод dir с помощью этой команды:

find .  \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
0 голосов
/ 31 декабря 2014

Это работает, потому что find ИСПЫТАНИЯ файлы для шаблона "* foo *":

find ! -path "dir1" ! -path "dir2" -name "*foo*"

, но он НЕ работает, если вы не используете шаблон (find не TEST файл). Таким образом, find не использует ранее оцененные значения " true " & " false " bools. Пример для не работающего варианта использования с обозначениями выше:

find ! -path "dir1" ! -path "dir2" -type f

Нет find ТЕСТИРОВАНИЯ! Поэтому, если вам нужно найти файлы без сопоставления с образцом, используйте -prune. Кроме того, использование prune find всегда быстрее, в то время как оно действительно пропускает эти каталоги, вместо того, чтобы сопоставлять их, или лучше не сопоставлять их. Так что в этом случае используйте что-то вроде:

find dir -not \( -path "dir1" -prune \) -not \( -path "dir2" -prune \) -type f

или

find dir -not \( -path "dir1" -o -path "dir2" -prune \) -type f

Привет

0 голосов
/ 31 августа 2015

Для FreeBSD пользователей:

 find . -name '*.js' -not -path '*exclude/this/dir*'
0 голосов
/ 22 апреля 2016

Если в каталогах поиска есть шаблон (в моем случае это чаще всего); Вы можете просто сделать это, как показано ниже:

find ./n* -name "*.tcl" 

В приведенном выше примере; он ищет во всех подкаталогах, начинающихся с "n".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...