Ограничение результатов от команды find при первом обходе глубины - PullRequest
2 голосов
/ 03 декабря 2011

Мне нужно написать скрипт, который находит все файлы, которые соответствуют шаблону именования, но когда я нахожу совпадение, я не хочу углубляться в какие-либо подкаталоги.Я понятия не имею, когда запускается скрипт, где могут быть найдены совпадения глубины.

Пример может помочь.Если я использую find, как это, чтобы найти мои каталоги Subversion:

find . -name .svn

Это приводит к чему-то вроде:

./java/.svn
./java/com/.svn
./java/com/squeakysand/.svn
./java/com/squeakysand/taglib/.svn
./java/com/squeakysand/taglib/dev/.svn
./java/com/squeakysand/taglib/logging/.svn
./java/com/squeakysand/taglib/text/.svn
./java/com/squeakysand/taglib/util/.svn
./resources/.svn

Но результат, который я действительно хочу этот конкретный пример, это простоПервый результат и последний результат.Другими словами, как только он находит каталог .svn внутри каталога java, я не хочу искать дальше в каталоге java (как каталог com в этом примере).Но я хочу получить результат в каталоге resources, поскольку он не находится в каталоге java.Но, как и в случае с каталогом java, теперь, когда я нашел каталог .svn в каталоге resources, я хочу прекратить дальнейший поиск в каталоге resources.

По сути, я хочувыполните поиск в глубину поиска соответствия, и когда я его найду, не углубляйтесь в этот путь.

Есть ли способ использовать find для этого или есть другая команда?или, может быть, комбинация команд?

Ответы [ 3 ]

0 голосов
/ 04 декабря 2011

Вам нужно объединить find тесты с -prune.Если я прав, find не имеет встроенного теста, который вам нужен.Рассмотрим следующий сценарий bash, testprefix.sh: (использует bashisms, не работает с sh)

#!/bin/bash
# Test if "$2" is a prefix of "$1"

test x"${1:0:${#2}}" = x"$2"

С этим сценарием вы можете вызвать find следующим образом:

найти.-name .svn (-exec ./testprefix.sh {} ./java/com/ \; -prune) -print

РЕДАКТИРОВАТЬ

find . -name .svn \( -exec ./testprefix.sh {} ./java/com \; -prune \) -or -print

(или замените -print тем действием, которое вы хотите выполнить с хорошими файлами)

Скобки \( и \) в этом случае не нужны, но сделайте его более понятным.

0 голосов
/ 16 декабря 2016

Полагаю, справочная страница find содержит пример почти того, что вам нужно, он просто расширен до .git и CVS подкаталогов. Копирование и вставка здесь с небольшими изменениями:

find . -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS \; -print -prune

Предположим, следующая структура каталогов проектов и связанных с ними административных каталогов SCM:

./project1/CVS
./gnu/project2/.svn
./gnu/project3/.svn
./gnu/project3/src/.svn
./project4/.git

В этом примере -prune предотвращает ненужный спуск в каталоги, которые уже были обнаружены (например, мы не ищем project3 / src, потому что мы уже нашли project3 / .svn), но обеспечивает обнаружение дочерних каталогов (project2 и project3) ,

0 голосов
/ 04 декабря 2011

Попробуйте это

{
cat -<<EOS
./java/.svn
./java/com/.svn
./java/com/squeakysand/.svn
./java/com/squeakysand/taglib/.svn
./java/com/squeakysand/taglib/dev/.svn
./java/com/squeakysand/taglib/logging/.svn
./java/com/squeakysand/taglib/text/.svn
./java/com/squeakysand/taglib/util/.svn
./resources/.svn
./resources/com/.svn
EOS
} |sed 's@/@ @g' \
  | sort\
  | awk '{if (prev == $2) {prev=$2} else {prev=$2; gsub(" ", "/", $0);print $0}}'

# output
./java/.svn
./resources/.svn

Обратите внимание, что в этом примере sed заменяет все символы '/' пробелами и в конце возвращает их обратно gsub(..).Поскольку в путях возможно наличие пробелов, вы, вероятно, захотите использовать другой символ для подстановки, но практически любой символ является допустимым именем файла Unix, поэтому, если у вас полностью открытая среда, вам придется взглянуть наваш вывод, чтобы убедиться, что он имеет смысл.

Надеюсь, это поможет.

...