Фильтруйте папки с именем timestamp - сопоставление с образцом или сопоставление с регулярным выражением с помощью утилиты find

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

Мой сценарий оболочки:

files=$(find $path -name $regex)

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

20161128-20:34:33:432813246
YYYYMMDD-HH:MM:SS:NS

Я не могу прийти к правильному регулярному выражению.

Я могу получить путь к файлам внутри папки с помощью регулярных выражений '*data.txt', так как я знаю имя файла внутри него.

Но это дает мне полный путь к файлу, что-то вроде

/path/20161128-20:34:33:432813246/data.txt

То, что я хочу, это просто:

/path/20161128-20:34:33:432813246

Пожалуйста, помогите мне в определении правильного регулярного выражения для моего требования

НОТА:

Я знаю, как обрабатывать данные после

files=$(find $path -name $regex)

Но так как сценарий должен быть универсальным для многих случаев использования, мне нужно только правильное регулярное выражение, которое необходимо передать.

2 ответа

Решение
  • По POSIX, find "s -name-path Первичные (тесты) используют шаблоны (известные как подстановочные выражения, глобусы) для сопоставления имен файлов и путей (в то время как шаблоны и регулярные выражения связаны между собой, их синтаксис и возможности значительно различаются; короче говоря: шаблоны синтаксически проще, но гораздо менее мощны).

    • -name и сопоставляет шаблон с частью базового имени (простого имени файла) только входного пути
    • -path сопоставляет шаблон с полным путем (полным путем)
  • И GNU, и BSD/macOS find реализовать нестандартные расширения:

    • -iname а также -ipath, которые работают как их совместимые со стандартом аналоги (на основе шаблонов), за исключением того, что они соответствуют без учета регистра.
    • -regex а также -iregex тесты на совпадение путей по регулярному выражению (регулярное выражение).
      • Предостережение: обе реализации предлагают как минимум 2 диалекта регулярных выражений на выбор (-E активирует поддержку расширенных регулярных выражений в BSD find и GNU find позволяет выбирать из нескольких диалектов с -regextype, но никакие два диалекта не являются абсолютно одинаковыми во всех двух реализациях - подробности смотрите внизу.

Если ваши имена папок следуют схеме именования фиксированной ширины, шаблон будет работать:

pattern='[0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]:[0-9][0-9]:[0-9][0-9]:[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'

Конечно, вы можете воспользоваться ярлыком, если не ожидаете ложных срабатываний:

pattern='[0-9]*-[0-9]?:[0-9]?:[0-9]?:[0-9]*'

Обратите внимание, как * а также ? в отличие от регулярных выражений, не являются символами дублирования (квантификаторами), которые относятся к предыдущему выражению, но сами по себе представляют любую последовательность символов (*) или любой отдельный символ (?).

Если мы соберем все это вместе:

files=$(find "$path" -type d -name "$pattern")
  • Важно заключить в кавычки ссылки на переменные, чтобы защитить их значения от нежелательных расширений оболочки, в частности, чтобы сохранить любые пробелы в пути и предотвратить преждевременное сглаживание оболочкой значения $pattern,

  • Обратите внимание, что я добавил -type d ограничить соответствие каталогам (папкам), что повышает производительность.


Дополнительная справочная информация:

Ниже приведена матрица элементов регулярных выражений в GNU find v4.6.0 / BSD find как найдено в macOS 10.12.1:

  • GNU find функции перечислены по типам, поддерживаемым -regextype вариант, с emacs быть по умолчанию.

    • Обратите внимание, что несколько posix-* Именованные типы регулярных выражений являются неправильными в том смысле, что они поддерживают функции, выходящие за рамки полномочий POSIX.
  • BSD find функции перечислены basic (используя опцию NO regex, которая подразумевает BRE со вкусом платформы) и extended (используя опцию -E, что подразумевает EREs со вкусом платформы).

Для кроссплатформенного использования, придерживаясь POSIX ERE (расширенные регулярные выражения) при использовании -regextype posix-extended с GNU find и используя -E с BSD find Это безопасно, но обратите внимание, что не все функции, которые вы можете ожидать, будут поддерживаться, особенно \b, \< / \> и ярлыки классов персонажей, такие как \d,

=================== GNU find ===================
== REGEX FEATURE: \{\}
TYPE: awk:                                        -
TYPE: egrep:                                      -
TYPE: ed:                                         ✓
TYPE: emacs:                                      -
TYPE: gnu-awk:                                    -
TYPE: grep:                                       ✓
TYPE: posix-awk:                                  -
TYPE: posix-basic:                                ✓
TYPE: posix-egrep:                                -
TYPE: posix-extended:                             -
TYPE: posix-minimal-basic:                        ✓
TYPE: sed:                                        ✓
== REGEX FEATURE: {}
TYPE: awk:                                        -
TYPE: egrep:                                      ✓
TYPE: ed:                                         -
TYPE: emacs:                                      -
TYPE: gnu-awk:                                    ✓
TYPE: grep:                                       -
TYPE: posix-awk:                                  ✓
TYPE: posix-basic:                                -
TYPE: posix-egrep:                                ✓
TYPE: posix-extended:                             ✓
TYPE: posix-minimal-basic:                        -
TYPE: sed:                                        -
== REGEX FEATURE: \+
TYPE: awk:                                        -
TYPE: egrep:                                      -
TYPE: ed:                                         ✓
TYPE: emacs:                                      -
TYPE: gnu-awk:                                    -
TYPE: grep:                                       ✓
TYPE: posix-awk:                                  -
TYPE: posix-basic:                                ✓
TYPE: posix-egrep:                                -
TYPE: posix-extended:                             -
TYPE: posix-minimal-basic:                        -
TYPE: sed:                                        ✓
== REGEX FEATURE: +
TYPE: awk:                                        ✓
TYPE: egrep:                                      ✓
TYPE: ed:                                         -
TYPE: emacs:                                      ✓
TYPE: gnu-awk:                                    ✓
TYPE: grep:                                       -
TYPE: posix-awk:                                  ✓
TYPE: posix-basic:                                -
TYPE: posix-egrep:                                ✓
TYPE: posix-extended:                             ✓
TYPE: posix-minimal-basic:                        -
TYPE: sed:                                        -
== REGEX FEATURE: \b
TYPE: awk:                                        -
TYPE: egrep:                                      ✓
TYPE: ed:                                         ✓
TYPE: emacs:                                      ✓
TYPE: gnu-awk:                                    ✓
TYPE: grep:                                       ✓
TYPE: posix-awk:                                  -
TYPE: posix-basic:                                ✓
TYPE: posix-egrep:                                ✓
TYPE: posix-extended:                             ✓
TYPE: posix-minimal-basic:                        ✓
TYPE: sed:                                        ✓
== REGEX FEATURE: \< \>
TYPE: awk:                                        -
TYPE: egrep:                                      ✓
TYPE: ed:                                         ✓
TYPE: emacs:                                      ✓
TYPE: gnu-awk:                                    ✓
TYPE: grep:                                       ✓
TYPE: posix-awk:                                  -
TYPE: posix-basic:                                ✓
TYPE: posix-egrep:                                ✓
TYPE: posix-extended:                             ✓
TYPE: posix-minimal-basic:                        ✓
TYPE: sed:                                        ✓
== REGEX FEATURE: [:digit:]
TYPE: awk:                                        ✓
TYPE: egrep:                                      ✓
TYPE: ed:                                         ✓
TYPE: emacs:                                      -
TYPE: gnu-awk:                                    ✓
TYPE: grep:                                       ✓
TYPE: posix-awk:                                  ✓
TYPE: posix-basic:                                ✓
TYPE: posix-egrep:                                ✓
TYPE: posix-extended:                             ✓
TYPE: posix-minimal-basic:                        ✓
TYPE: sed:                                        ✓
== REGEX FEATURE: \d
TYPE: awk:                                        -
TYPE: egrep:                                      -
TYPE: ed:                                         -
TYPE: emacs:                                      -
TYPE: gnu-awk:                                    -
TYPE: grep:                                       -
TYPE: posix-awk:                                  -
TYPE: posix-basic:                                -
TYPE: posix-egrep:                                -
TYPE: posix-extended:                             -
TYPE: posix-minimal-basic:                        -
TYPE: sed:                                        -
== REGEX FEATURE: \s
TYPE: awk:                                        ✓
TYPE: egrep:                                      ✓
TYPE: ed:                                         -
TYPE: emacs:                                      ✓
TYPE: gnu-awk:                                    ✓
TYPE: grep:                                       -
TYPE: posix-awk:                                  ✓
TYPE: posix-basic:                                -
TYPE: posix-egrep:                                ✓
TYPE: posix-extended:                             ✓
TYPE: posix-minimal-basic:                        -
TYPE: sed:                                        -
=================== BSD find ===================
== REGEX FEATURE: \{\}
TYPE: basic:                                      ✓
TYPE: extended:                                   -
== REGEX FEATURE: {}
TYPE: basic:                                      -
TYPE: extended:                                   ✓
== REGEX FEATURE: \+
TYPE: basic:                                      -
TYPE: extended:                                   -
== REGEX FEATURE: +
TYPE: basic:                                      -
TYPE: extended:                                   ✓
== REGEX FEATURE: \b
TYPE: basic:                                      -
TYPE: extended:                                   -
== REGEX FEATURE: \< \>
TYPE: basic:                                      -
TYPE: extended:                                   -
== REGEX FEATURE: [:digit:]
TYPE: basic:                                      ✓
TYPE: extended:                                   ✓
== REGEX FEATURE: \d
TYPE: basic:                                      -
TYPE: extended:                                   -
== REGEX FEATURE: \s
TYPE: basic:                                      -
TYPE: extended:                                   ✓

Когда у вас есть полный путь к файлу, вам не нужно регулярное выражение для извлечения имени каталога.

dirname "/path/20161128-20:34:33:432813246/data.txt" 

дам тебе

/path/20161128-20:34:33:432813246

Если вы действительно хотите регулярное выражение, попробуйте это:

\d{8}-\d{2}:\d{2}:\d{2}:\d{9}
Другие вопросы по тегам