Вопрос или проблема
Я хотел бы выполнить команду find
и получить некоторые файлы/каталоги в директории рабочего стола, используя опцию regex
команды с символом кареткой ^
Как вы знаете, каретка ^
соответствует началу строки, и я хотел бы получить все файлы/каталоги, начинающиеся с буквы t
; я использовал следующую команду find . -regex "^./t"
, но, как оказалось, она будет соответствовать только файлу/папке, имя которого — простое t!
Я знаю, что regex будет соответствовать всему пути
, а не только имени файла
. Но почему все эти файлы не совпадают, если они начинаются с ./t
.
./tcpdump.txt
./t.txt
./test.sh
./trade.txt
./torbrowser.desktop
./token.txt
PS: Этот regex сработал для меня, ^./t.*
, но я все еще не понимаю поведение каретки в оригинальной команде
Опция -regex
ожидает шаблон, который соответствует всему файлу. См. man find
:
-regex pattern
Имя файла соответствует шаблону регулярного выражения. Это совпадение для всего пути, а не поиск. Например, для совпадения файла с именем ./fubar3 вы можете использовать регулярное выражение ‘.*bar.’ или ‘.*b.*3′, но не ‘f.*r3′. Регулярные выражения, которые понимает команда find, по умолчанию являются регулярными выражениями Emacs, но это можно изменить с помощью опции -regextype.
Каретка бессмысленна в этом контексте, поскольку, как объяснялось выше, -regex
должен соответствовать всему, так что по сути ^
и $
подразумеваются.
Вы указали ^./t
, что означает “ищите любой символ” (помните, что .
означает “любой символ” в регулярных выражениях, это не значит буквальный .
) за которым следует /
, а затем одна буква t
и больше ничего.
Что вам нужно здесь, так это оператор -name
, который принимает глобальные шаблоны, а не регулярные выражения, и соответствует только имени файла, а не всему пути. Поэтому, чтобы найти все файлы/каталоги, имена которых начинаются с t
, используйте:
find . -name "t*"
Глобальный шаблон t*
означает “t, за которым следует 0 или более символов”. Если вы действительно хотите сделать это с помощью -regex
, хотя это только усложняет задачу, вам нужно указать, что вы позволяете любому символу следовать за t
, например, так:
find . -regex '.*/t.*'
Это регулярное выражение означает “совпадать с максимально возможным количеством символов (включая 0), пока не встретится последний /
, а затем t
, за которым следуют любые другие символы.
Тот факт, что регулярное выражение всегда соответствует всему пути, означает, что каретка и доллар избыточны: должен совпадать весь путь, а не только его подстрока. Или вы всегда можете представить, что регулярное выражение начинается с каретки и заканчивается долларом, даже если вы их не вводите.
Ответ или решение
Команда find
с опцией -regex
может вводить в заблуждение, особенно если вы пытаетесь использовать символ каретки ^
для поиска файлов, начинающихся на определённую букву. Давайте разберёмся, почему ваш исходный запрос find . -regex "^./t"
не работает так, как вы ожидали.
Во-первых, важно понимать, что опция -regex
ожидает регулярное выражение, которое соответствует всему пути к файлу, а не только его имени. Это означает, что ваше регулярное выражение должно учитывать не только имя файла, но и все каталоги, предшествующие ему в пути.
Когда вы используете ^./t
, ваше регулярное выражение фактически говорит: «совпадение начинается с ./t
и ничем не продолжается». Это означает, что будет найден только файл или папка с именем t
в каталоге, а не файлы, начинающиеся с t
, как, например, test.sh
или token.txt
, так как они имеют дополнительные символы после t
.
Ваша гипотеза о том, что символ каретки ^
совпадает только с началом строки, верна, и в контексте -regex
это действительно не нужно. Символы ^
и $
подразумеваются: регулярное выражение должно соответствовать всему пути к файлу.
Если вы хотите найти все файлы и каталоги, начинающиеся с буквы t
, рекомендуется использовать оператор -name
, который принимает глобальные шаблоны (globs) и учитывает только имя файла, а не весь путь. Например, команда:
find . -name "t*"
выполнит вашу задачу, находя все элементы, имена которых начинаются с буквы t
. Здесь t*
означает «начинается с t
и за ним может следовать 0 или более символов».
Если вы всё же хотите использовать регулярные выражения, вам нужно будет сделать следующее:
find . -regex '.*/t.*'
Это выражение «согласовывает с любым количеством символов (включая 0) до последнего /
, а затем ищет t
и любые символы после этого».
Таким образом, чтобы избежать путаницы:
- Используйте
-name
для простых задач поиска по имени файла. - Если используете
-regex
, не забудьте учитывать, что выражение должно совпадать с полным путем и это может делать использование^
и$
излишним.
Надеюсь, это поможет прояснить поведение команды find
с опцией -regex
и сделает ваш поиск более эффективным.