Что меня смущает, так -prune
это то, что это действие (как -print
), а не тест (как -name
). Он изменяет список «дел», но всегда возвращает true .
Общий шаблон для использования -prune
таков:
find [path] [conditions to prune] -prune -o \
[your usual conditions] [actions to perform]
Вы почти всегда хотите -o
(логическое ИЛИ) сразу после -prune
, потому что эта первая часть теста (вплоть до включительно -prune
) вернет false для того, что вам действительно нужно (то есть: того, что вы не хотите исключать).
Вот пример:
find . -name .snapshot -prune -o -name '*.foo' -print
Это найдет файлы "* .foo", которые не находятся в каталогах ".snapshot". В этом примере -name .snapshot
составляет [conditions to prune]
, и -name '*.foo' -print
есть [your usual conditions]
и [actions to perform]
.
Важные замечания :
Если все, что вы хотите сделать, это распечатать результаты, которые вы могли бы использовать для пропуска -print
действия. Как правило, вы не хотите делать это при использовании -prune
.
Поведение поиска по умолчанию - «и» все выражение с -print
действием, если -prune
в конце нет никаких действий, кроме (по иронии судьбы). Это означает, что написание этого:
find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS
эквивалентно написанию этого:
find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
Это означает, что он также распечатает имя каталога, который вы удаляете, что обычно не то, что вы хотите. Вместо этого лучше явно указать -print
действие, если вы этого хотите:
find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS
Если ваше «обычное состояние» совпадает с файлами, которые также соответствуют вашему состоянию обрезки, эти файлы не будут включены в выходные данные. Это можно исправить, добавив -type d
предикат в условие обрезки.
Например, предположим, что мы хотели .git
удалить любую директорию, с которой начинали (это, по общему признанию, несколько надумано - обычно вам нужно только точно удалить названную вещь .git
), но кроме этого, хотелось видеть все файлы, включая такие, как файлы .gitignore
. Вы можете попробовать это:
find . -name '.git*' -prune -o -type f -print # DON'T DO THIS
Это не будет включать .gitignore
в вывод. Вот исправленная версия:
find . -name '.git*' -type d -prune -o -type f -print # DO THIS
Дополнительный совет: если вы используете версию GNU find
, страница texinfo для find
содержит более подробное объяснение, чем ее man-страница (как это верно для большинства утилит GNU).
Лоуренс Гонсалвес
источник
-prune
не только работает с каталогами (но для каталогов он также предотвращает вход в каталоги, соответствующие этому условию, то есть здесь каталоги, соответствующие этому-name .snapshot
).-prune
кстати, это не само по себе. Проблема в том, что оператор или «замыкает накоротко», и / или имеет более низкий приоритет, чем и. Конечным результатом является то, что если файл с именем вызван,.snapshot
он будет соответствовать первому-name
,-prune
затем ничего не будет делать (но вернет true), а затем или возвращает true, поскольку его левый аргумент был true. Действие (например:)-print
является частью его второго аргумента, поэтому у него никогда нет шансов выполнить.-print
в конце, теперь я могу перестать добавлять\! -path <pattern>
в дополнение к-prune
Обычно родной способ, которым мы делаем вещи в Linux, и способ, которым мы думаем, слева направо.
Таким образом, вы бы сначала написать и написать то, что вы ищете:
Затем вы, вероятно, нажали Enter и поняли, что получаете слишком много файлов из каталогов, которые вы не хотите. Давайте исключим / media, чтобы избежать поиска ваших подключенных дисков.
Теперь вы должны просто добавить следующее к предыдущей команде:
итоговая команда:
............... | <--- Включить ---> | .................... | <- -------- Исключить ---------> |
Я думаю, что эта структура намного проще и соответствует правильному подходу
источник
find
он достаточно умен, чтобы-prune
сначала обработать предложение. Хм, интересно.-prune
с этого момента ./media
, заметив, что он не*.php
вызывается, и затем проверил, находится ли он в данный момент внутри/media
, увидев, что он есть, и, следовательно, пропустив все это поддерево. Это все еще слева направо, это просто не имеет значения, пока обе проверки не пересекаются.Остерегайтесь, что -prune не предотвращает спуск в любой каталог, как говорили некоторые. Это предотвращает спуск в каталоги, которые соответствуют тесту, к которому он применяется. Возможно, некоторые примеры помогут (см. Пример для регулярных выражений внизу). Извините за это так долго.
источник
find . -name test -prune -o -print
: iow,-prune
это действие, которое также работает над файламиДобавление к советам, данным в других ответах (у меня нет представителя для создания ответов) ...
При объединении
-prune
с другими выражениями в поведении есть небольшая разница в зависимости от того, какие выражения используются.Пример @Laurence Gonsalves найдет файлы "* .foo", которые не находятся в каталогах ".snapshot": -
Тем не менее, это несколько другое сокращение, возможно, непреднамеренно, также перечислит
.snapshot
каталог (и любые вложенные каталоги .snapshot): -Причина (в соответствии с man-страницей в моей системе): -
То есть второй пример является эквивалентом ввода следующего, тем самым изменяя группировку терминов:
По крайней мере, это было видно на Solaris 5.10. Пользуясь различными разновидностями * nix около 10 лет, я только недавно искал причину, по которой это происходит.
источник
-prune
с и без-print
!Чернослив не рекурсивно при любом переключении каталога.
Со страницы руководства
В основном это не будет спускаться ни в какие подкаталоги.
Возьмите этот пример:
У вас есть следующие каталоги
Если вы запускаете
find -name test2
:Он вернет оба каталога
Если вы запускаете
find -name test2 -prune
:Он вернет только / home / test2, поскольку не попадет в / home / test2 для поиска / home / test2 / test2
источник
Я не эксперт в этом (и эта страница была очень полезна вместе с http://mywiki.wooledge.org/UsingFind )
Только что был замечен
-path
путь, который полностью соответствует строке / пути, которая идет сразу послеfind
(.
в этих примерах), где as-name
соответствует всем базовым именам.блокирует каталог .git в вашем текущем каталоге ( как вы нашли в
.
)рекурсивно блокирует все подкаталоги .git.
Обратите внимание, что
./
это чрезвычайно важно!-path
должен соответствовать путь, привязанный к.
или к чему-либо, пришедшему сразу после поиска, если вы получаете совпадения с ним (с другой стороны или '-o
'), который, вероятно, не удаляется! Я наивно не знал об этом, и это заставило меня использовать -path, когда замечательно, когда вы не хотите удалять все подкаталоги с одним и тем же базовым именем: Dисточник
find bla/
то говорите, что вам понадобится -pathbla/
.git (или если*
вместо этого вы пихаете a вперед, он будет вести себя как -name)Показать все, включая самого dir, но не скучное содержимое:
источник
Если вы прочитаете здесь все хорошие ответы, то я понимаю, что все следующее дает одинаковые результаты:
Но последнее займет намного больше времени, так как все еще ищет все в dir1. Я полагаю, что реальный вопрос заключается в том, как
-or
выводить нежелательные результаты, фактически не ища их.Так что я думаю, что обрезка означает не приличные прошлые матчи, а пометить как выполненные ...
http://www.gnu.org/software/findutils/manual/html_mono/find.html «Это, однако, не связано с действием действия« -prune »(которое только предотвращает дальнейшее снижение, оно не гарантирует мы игнорируем этот элемент). Вместо этого этот эффект связан с использованием '-o'. Поскольку левая часть условия "или" успешно выполнена для ./src/emacs, нет необходимости оценивать правую hand-side ('-print') вообще для этого конкретного файла. "
источник
find
строит список файлов. Он применяет предикат, который вы предоставили каждому, и возвращает те, которые прошли.Эта идея,
-prune
означающая исключение из результатов, меня действительно смутила. Вы можете исключить файл без удаления:Все, что
-prune
нужно, это изменить поведение поиска. Если текущее совпадение является каталогом, оно говорит: «Эйfind
, этот файл, который вы только что сопоставили, не спускайтесь в него» . Он просто удаляет это дерево (но не сам файл) из списка файлов для поиска.Это должно быть названо
-dont-descend
.источник
Есть довольно много ответов; некоторые из них слишком сложны для теории. Я уйду, почему мне нужно было подрезать один раз, так что, может быть, объяснение типа «в первую очередь / пример» кому-то пригодится :)
проблема
У меня была папка с примерно 20 каталогами узлов, каждый из которых имел свой
node_modules
каталог, как и ожидалось.Как только вы попадаете в любой проект, вы видите каждый
../node_modules/module
. Но вы знаете, как это. Почти у каждого модуля есть зависимости, так что то, на что вы смотрите, больше похоже наprojectN/node_modules/moduleX/node_modules/moduleZ...
Я не хотел тонуть со списком с зависимостью зависимости ...
Зная
-d n
/-depth n
, это не помогло бы мне, так как каталог main / first node_modules, который я хотел получить для каждого проекта, был на разной глубине, например:Как я могу получить первый список путей, заканчивающихся на первом,
node_modules
и перейти к следующему проекту, чтобы получить то же самое?Войти
-prune
Когда вы добавите
-prune
, у вас все равно будет стандартный рекурсивный поиск. Каждый «путь» анализируется, и каждая находка выплевывается иfind
продолжает копаться, как хороший парень. Но это рытье для большего,node_modules
чего я не хотел.Таким образом, разница в том, что в любом из этих разных путей,
-prune
выfind
перестанете копать дальше вниз по этому конкретному проспекту, когда он найдет ваш предмет. В моем случаеnode_modules
папка.источник