| find: исключение папки из области поиска |
|
| Добавил(а) microsin |
|
Как в команде find исключить из поиска определенную папку? Чтобы исключить папку из поиска в команде find, используйте параметр -path в сочетании с -prune. Вот самый распространенный и правильный способ (искл_папка в пути поиска не будет просматриваться): find /путь/поиска -path "/путь/поиска/искл_папка" -prune -o -name "*.txt" -print Как это работает: -path "/путь/поиска/искл_папка" — находит полный путь к папке, которую нужно исключить. Выглядит сложно, но ничего не поделаешь - этим мы платим за универсальность инструмента find. Конкретные примеры: 1. Исключаем папку `cache` в текущей директории: find . -path "./cache" -prune -o -name "*.log" -print 2. Исключаем папку на любом уровне вложенности (например, все папки `node_modules`): find . -path "*/node_modules" -prune -o -name "*.js" -print 3. Исключаем сразу несколько папок (объединяем через `-o`): find . \( -path "./tmp" -o -path "./backup" \) -prune -o -name "*.txt" -print Важный нюанс (частая ошибка). Если вы пишете: find . -path "./cache" -prune -name "*.log" # ❌ НЕПРАВИЛЬНО ... то find найдет файлы *.log только внутри папки cache, а не снаружи. Чтобы искать снаружи, всегда используйте конструкцию с -o и обязательно ставьте `-print` в конце: find . -path "./cache" -prune -o -name "*.log" -print # ✅ ПРАВИЛЬНО Альтернативный способ исключения папки (через grep -v). Если вам нужно исключить папку, но она находится глубоко и с -prune разобраться сложно, можно отфильтровать результат через grep: find . -name "*.txt" | grep -v "./cache/" Минус: этот способ медленнее, так как find всё равно сначала обойдет всю папку cache (это может быть долго, если папка большая), а потом просто скроет результат. -prune же физически пропускает обход, что намного быстрее. [Как для find исключить несколько папок?] Для исключения нескольких папок в find нужно объединить условия через -o (логическое ИЛИ) в группах с -prune. Группа определяется скобками, которые нужно экранировать символом '\'. Вот универсальный шаблон: find . \( -path "./папка1" -o -path "./папка2" -o -path "./папка3" \) -prune -o -name "*.txt" -print Ключевые моменты: \( ... \) — группировка условий. Конкретные примеры: 1. Исключаем из поиска папки cache, tmp и backup в текущей директории: find . \( -path "./cache" -o -path "./tmp" -o -path "./backup" \) -prune -o -name "*.log" -print 2. Исключаем папки на любом уровне вложенности (например, все node_modules, .git и dist): find . \( -path "*/node_modules" -o -path "*/.git" -o -path "*/dist" \) -prune -o -name "*.js" -print 3. Исключаем папки с пробелами или спецсимволами в имени (с помощью двойных кавычек): find . \( -path "./My Documents" -o -path "./Downloads" \) -prune -o -name "*.pdf" -print Если папок много — используйте переменную или файл. Вариант A: список в переменной окружения (через -o): exclude_dirs="-path ./cache -o -path ./tmp -o -path ./backup" Вариант B: через bash-массив (удобно, если пути сложные): exclude=("./cache" "./tmp" "./backup") find . \( "${args[@]}" \) -prune -o -name "*.txt" -print Вариант C: читаем список из файла (по одной папке на строку): # files.txt содержит: find . $(awk '{print "-path " $1 " -o"}' files.txt | sed '$ s/-o$//') -prune -o -name "*.txt" -print Альтернатива (проще, но медленнее). Если папок много и производительность не критична, можно отфильтровать через `grep -v` с опцией `-E` (расширенными регулярками): find . -name "*.txt" | grep -v -E "(./cache|./tmp|./backup)" Или исключить папки на любом уровне: find . -name "*.txt" | grep -v -E "(node_modules|\.git|dist)" Минус: find всё равно физически обходит исключённые папки, что может быть медленно для больших директорий (например, node_modules). Если использовать -prune, то будет быстрее, так как пропускает обход. Частая ошибка исключения папок, так делать неправильно: find . -path "./cache" -prune -o -path "./tmp" -prune -o -name "*.txt" -print Работать будет, но если папок много — код становится громоздким и нечитаемым. Лучше группировать все условия в одни скобки перед одним -prune. Правильно: find . \( -path "./cache" -o -path "./tmp" \) -prune -o -name "*.txt" -print
|