How to Use Regex in find regex and Other Commands Fast
Use regex in find and neighboring commands: find -regex matches the full path, pick the regextype, case-insensitive iregex, and how locate and pgrep differ.

"Use a regex" means something different in every command that offers it: what the pattern is matched against, which syntax it speaks, and whether it is anchored. For find the surprise is that the pattern is checked against the entire path. This post collects the rules for find and the commands people use alongside it, as a companion to find with regex and prune. Examples use GNU findutils 4.10.
find -regex
find . -type f -regextype posix-extended -regex '.*/(report|summary)-[0-9]{4}\.csv'
find . -type f -iregex '.*\.jpe?g'
find . -regextype helpThe path is matched from the first character to the last, as printed: for a search starting at ., that includes ./. So the pattern must account for the directory part, usually with a leading .*/. The default dialect in GNU find is emacs, where + and ? are special and | is written \|, which is why a pattern from another tool misbehaves. -regextype help lists the options: emacs, posix-basic, posix-extended, posix-egrep and a few more. On macOS and BSD, write find -E . -regex '...', and GNU's option does not exist there.
Glob or regex?
find . -name '*.log'
find . -name 'report-????.csv'
find . -regex '.*/report-[0-9]\{4\}\.csv'A glob on the base name covers most searches, with less to remember. Use the regex only when you need alternation, a digit-only run or a match on directory components. -name matches the file name alone and needs no path prefix; -path takes a glob against the whole path.
Filtering with a pipe
find . -type f -print0 | grep -zE '/(report|summary)-[0-9]{4}\.csv$' | xargs -0 ls -lWhen find's dialects get in the way, produce the list and filter it with a tool whose syntax you know. NUL-separated lists keep names with spaces and newlines intact, and grep -z reads them. This is slower than an in-find test on huge trees, because every path is formatted and piped, but it is portable across GNU and BSD with -E grep. Be careful that $ then anchors at the end of each NUL-separated record.
Neighbors with their own rules
locate -r '/nginx\.conf$'
pgrep -af '^python3? .*worker'
pgrep -x sshd
ls | grep -E '^2026-.*\.log$'locate -r uses POSIX basic expressions against the full path stored in the index; see locate and updatedb. pgrep uses extended expressions against the process name by default, and with -f against the full command line; -x demands an exact name. A pattern like python without -x also matches python3 and any process with it in the name, including your own pgrep invocation when -f is on, which is a classic false positive. Parsing ls output breaks on odd names; use find or a glob.
Where this does not apply
Regexes cannot express "modified in the last day" or "bigger than 1 MB", which are find tests; combine them with -mtime and -size as in modification time searches. Where speed matters on a large tree, prune early and use cheap tests before the regex. The differences between dialects are tabulated in regex differences across tools.
How find matches the whole path
The -regex test in find matches the whole path as it is printed, not just the file name, which is why a pattern needs a leading .* to match a name deep in a tree. The dialect is emacs-style in GNU find unless you choose another with -regextype, and BSD find uses basic expressions unless -E is given before the path. That means find . -regex '.*\.(txt|md)' finds nothing on GNU find in the default dialect, because the parentheses and the pipe are literal, and works after adding -regextype posix-extended. The case-insensitive variant is -iregex. The path starts with whatever you gave on the command line, so a search that begins with ./ has paths that start with ./, and a search that begins with an absolute path has absolute paths, which changes what an anchored pattern means.
The previous post on prune patterns covers how to skip directories efficiently. Here the point is the matching itself, and that the same pattern behaves differently depending on how the starting path was written.
When a glob is the better answer
For file names, a glob is usually clearer than a regular expression. -name '*.log' matches the base name against a shell-style pattern, and -iname ignores case. The patterns are simpler and quicker to read, and they cannot be mistaken for a regular expression. Use -path for a glob against the whole path, and note that its star also matches slashes, unlike a shell glob. Regular expressions pay off when the rule has alternation, repetition counts or character classes that a glob cannot express, such as names ending in a date in a given format. Quote every pattern so the shell does not expand it before find sees it, a mistake that works until the current directory happens to contain a matching file. The two styles can be combined in one command, and ordering the cheap test first, such as a type or name test, makes the search faster because the costlier test runs on fewer files.
Piping into other tools and null-separated output
When find cannot express the filter, pipe its output to grep, awk or sed, and watch for names with spaces and newlines. Use -print0 and tools that read null-separated input, such as xargs -0, grep -z and sort -z, so any legal file name survives the trip. A plain newline-separated pipeline is fine for names you control and breaks on the first name with a newline, which is rare and a classic security problem in scripts that handle uploaded files. Other tools have regular expression options of their own: locate -r takes a basic expression against the whole path from the index, and the shell's own [[ $name =~ regex ]] uses extended syntax in Bash, with the match stored in BASH_REMATCH. Each of these has its own flavor and quoting, and keeping a note of which one you are using prevents a lot of confusion.
For renaming many files, test the command with a dry run first, since a pattern that matches more than expected can overwrite files, and printing the planned new names costs nothing.
A short decision guide
To choose the tool for file selection, ask what the rule looks at. A name pattern with one or two alternatives is a glob with -name. A rule on the whole path with a structure, such as a version directory followed by a date, is a regular expression with -regex. A rule on content is a job for grep on the files that find lists. A rule on age, size or type has its own tests and needs no pattern. Combine tests with the logical operators and put the cheap ones first. Whatever you pick, preview the list before acting on it, and keep the command in a script with a comment describing what the pattern is meant to select, so the next person does not have to decode it.
See the findutils regular expressions and pgrep(1).


