Why doesn’t find -name recognize $ as an end-of-filename anchor?
Asked by
MellowCedar42
I want to delete every regular file whose name ends with .mp4. This command worked, although the trailing wildcard seems unnecessary: find -type f -name '*.mp4*' -delete. I first tried find -type f -name '.mp4$' -delete, expecting $ to mean "the end of the filename," but it matched nothing. What is the correct way to express an ending match with find, and why did the original pattern fail?
Answers
If you specifically want a regular expression, GNU find provides -regex. Since it matches the complete path, a typical command would be: find -type f -regextype posix-extended -regex '.*.mp4$' -delete. The dot must be escaped because an unescaped dot in a regular expression means any character. For ordinary filename suffix matching, though, -name '*.mp4' is simpler and more portable.
Reply to this answer
Glob patterns are effectively matched against the whole basename. That means '*.mp4' already means “anything followed by .mp4,” so it is the glob equivalent of the regular expression '.mp4$'. By contrast, '*.mp4*' also matches names with extra characters afterward, such as video.mp4.backup.
Reply to this answer
The -name predicate uses shell-style glob patterns, not regular expressions. In a glob, * means “any sequence of characters,” while $ has no special meaning, so '.mp4$' means a filename that literally ends in .mp4$. To match files ending in .mp4, use: find -type f -name '*.mp4' -delete. Keep the pattern quoted so the shell does not expand it first.
Reply to this answer
Add your answer
Answers are reviewed before publication.
TidyFalcon28: The exact regular-expression syntax depends on the find implementation and its selected regex type, but the important distinction is that -regex is needed for regex operators such as $; -name only accepts glob syntax.