Regex in find – OS X

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

 find -E . -name '.*[sS]{1}[0-9]{1,2}[\.]?[eE]{1}[0-9]{1,2}.*\.mkv' 

Я не получаю никаких результатов при find , однако, если я использую одно и то же регулярное выражение в сочетании с ls|grep -E '....' , файлы будут найдены, как ожидалось.

-name принимает шаблоны подстановочных знаков , а не регулярные выражения и совпадения имени файла, а не его полный путь. Используйте -regex (или -iregex ) для соответствия регулярному выражению, но будьте осторожны, чтобы он соответствовал полному пути. Здесь вы можете сделать:

 LC_ALL=C find -E . -iregex '.*s[0-9]{1,2}\.?e[0-9]{1,2}[^/]*\.mkv' 

Здесь мы заменяем второй .* [^/]* , то есть последовательность не / символов, чтобы убедиться, что шаблон перед ним совпадает с именем файла, а не с компонентами каталога.

LC_ALL=C локаль на C с LC_ALL=C , мы убедились . соответствует любому байту и [^/] любому байту, кроме одного для / поскольку в противном случае вы могли бы столкнуться с проблемами с именами файлов или каталогов, закодированными в другом наборе символов, как ваш язык. Фиксация языкового стандарта на C также гарантирует e только совпадения на e и Es на s и S ) с -iregex .

Обратите внимание, что [\.] Совпадает с обратной косой чертой или точкой. Чтобы соответствовать точке, это либо \. или [.] . Также x{1} совпадает с x , поэтому я удалил эти {1} для упрощения.

Проверьте свою страницу руководства. Обратите внимание, что ни один из -E , -regex или -iregex является стандартным .

Это можно упростить

 LC_ALL=C find -E . -iregex '.*s[0-9]{1,2}\.?e[0-9][^/]*\.mkv' 

Поскольку вторая цифра, если таковая имеется, также будет соответствовать [^/] .

Стандартный эквивалент с использованием шаблонов подстановок будет выглядеть так:

 LC_ALL=C find . -name '*[sS][0-9][0-9].[eE][0-9]*.mkv' \ -o -name '*[sS][0-9].[eE][0-9]*.mkv' \ -o -name '*[sS][0-9][0-9][eE][0-9]*.mkv' \ -o -name '*[sS][0-9][eE][0-9]*.mkv' 

шаблоны подстановочных знаков, в отличие от расширенных регулярных выражений, не имеют оператора чередования или эквивалента ? или {n,p} , поэтому нам нужно 4 шаблона, чтобы охватить все возможности.

Вы также можете использовать оболочку с рекурсивным глобированием и расширенными шаблонами подстановок, такими как zsh :

 setopt extendedglob ls -lrtd -- **/(#i)*s<->e<->*.mkv 
  • **/ рекурсивный поиск
  • (#i) нечувствительность к регистру
  • <-> любое десятичное число

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

find dir -name просто поддерживает символы glob-файла с именем файла shell, как man fnmatch .

Некоторые поисковые реализации поддерживают нестандартные расширения для регулярных выражений. Проверьте свою страницу поиска.