find: список всех каталогов, кроме номеров с именами и именами их детей

Я запускаю следующее, чтобы найти все каталоги без номера в них (не включая исходный путь):

find /path/2/directory -type d -name '[!0-9]*' 

Проблема в том, что он находит каталоги, которые являются подкаталогами каталогов, которые имеют числа.

Пример:

 /path/2/directory/20160303/backup 

или даже

 /path/2/directory/backup20160303a/backup 

Есть ли способ предотвратить поиск от таких каталогов?

Я не могу решить эту проблему, ограничивая глубину, глубина может меняться.

Пример:

 /path/2/directory/subdirectory/20160303/backup 

  • странное поведение при сопоставлении шаблонов sed
  • Почему эта команда Bash использует regex, не заменяя мои скобки?
  • Поиск дубликатов экземпляров тега в файле
  • Как найти и заменить содержимое файлов, которые соответствуют шаблону?
  • Строка состояния соответствует reg.expression
  • regexp в ksh для расширений tgz, tar.tgz
  • Ошибка сравнения регулярных выражений Bash для шестнадцатеричного байта \ x01
  • Поиск и замена VIM
  • 4 Solutions collect form web for “find: список всех каталогов, кроме номеров с именами и именами их детей”

    Используйте -prune чтобы игнорировать эти каталоги:

     find /path/to/directory -name '*[0-9]*' -prune -o -type d -print 

    хотя, если вы используете настройку gnu , вы можете использовать языковой стандарт C при запуске выше, см. комментарий Stéphane ниже.

    Если вы не хотите, чтобы поиск происходил за определенным соответствием, вы должны использовать -prune а не eg -path или фильтровать вывод find с grep -v

    Чтобы проверить ситуацию, создайте среду с некоторыми дополнительными файлами и поддиректорами, чтобы вы могли проверить свою find чтобы не отображать нежелательный материал:

     mkdir -p tmp/2/abc/def touch tmp/2/abc/def/file1 mkdir -p tmp/2/abc/9876/xyz touch tmp/2/abc/9876/xyz/file2 tree tmp/ 

    дает:

     tmp └── 2 └── abc ├── 9876 │  └── xyz │  └── file2 └── def └── file1 

    Если вы find tmp/2/abc \! -path "*[0-9]*" find tmp/2/abc \! -path "*[0-9]*" как было предложено @terdon, вывод будет пустым, потому что -path не просто учитывает каталоги, начинающиеся ниже abc а весь путь, который включает в себя 2 . Так что это не то, что вы хотите.

    Если вы find tmp/2/abc -type d | grep -vE '/[0-9-]+(/|$)' find tmp/2/abc -type d | grep -vE '/[0-9-]+(/|$)' , как было предложено @cas, вы обнаружите, что он ничего не печатает, потому что он соответствует не только файлам, от которых вы поиск, но также каталог с именем 2 . Кроме того, для этого потребуется найти первую прогулку по всему дереву под 9876 и если там будет несколько сотен тысяч предметов, ходьба (и фильтрация) займет определенное количество времени.

    Если вы это сделаете:

     find tmp/2/abc -type d -name '[!0-9]*' -print 

    вы увидите, что выход включает в себя путь tmp/2/abc/9876/xyz . Чтобы избавиться от этого, -prune то, что вы не хотите с -prune : -prune :

     find tmp/2/abc -type d -name '[!0-9]*' -print -o -name '[0-9]*' -prune 

    который дает:

     tmp/2/abc tmp/2/abc/def 

    вы можете немного улучшить эффективность этого путем замены обрезки и печати, что и сделал @don_cristti в его усилении этого ответа.

    Я думаю, что вы ищете -path :

      -path pattern File name matches shell pattern pattern. The metacharacters do not treat `/' or `.' specially; so, for example, find . -path "./sr*sc" will print an entry for a directory called `./src/misc' (if one exists). 

    Он ищет весь путь для каждого файла / каталога для данного шаблона. Итак, если у вас есть такая структура каталогов:

     $ tree . ├── 111 │  └── foo │  └── bar ├── bar │  └── foo │  └── baz └── foo └── 111 └── bar 9 directories, 0 files 

    Вы можете использовать find следующим образом:

     $ find /path/to/directory/ \! -path "*[0-9]*" . ./foo ./bar ./bar/foo ./bar/foo/baz 

    Или, с GNU find :

     find /path/to/directory/ -not -path "*[0-9]*" 

    Так как это нужно будет спуститься в каждый каталог, чтобы проверить его имя, оно будет значительно медленнее на больших деревьях каталогов, чем решение @ Anthon с черновиком. Если у вас нет тысяч каталогов, все должно быть хорошо.

    Легко использовать grep (или awk или sed или perl т. Д.), Чтобы удалить такие каталоги из вывода find :

     find /path/to/directory -type d | grep -vE '/[0-9-]+(/|$)' 

    Примечание. Я включил - в класс символов, потому что датированные каталоги иногда YYYY-MM-DD, а не только YYYYMMDD

    Linux и Unix - лучшая ОС в мире.