For instance, want to match all files in this directory and sub-directories that end with .ly
or .ily
. So far, find . -name "*.*ly" -print
is the closest I can get but this could potentially find files names I don't want.
3 Answers
You can use the -o
option, which is an "or" option.
The simplest version would be
find . -name '*.ly' -o -name '*.ily'
This works because -print
is the default action.
But if the -print
was just an example then you might need to group the two clauses together
find . \( -name '*.ly' -o -name '*.ily' \) -print
zsh
globs have a **/
recursive globbing operator and glob qualifiers so can do most of what find
can do. Zero-or-one of something, aka optional something can be done with (|something)
there (nothing or something), though there's also a (#cX,Y)
similar to regex {X,Y}
as an arbitrary interval operator (needs set -o extendedglob
):
print -rC1 -- **/*.(|i)ly(N)
Would have the advantage over the find
equivalent of giving you a sorted list, skipping hidden files (use the D
qualifier if you want them), avoiding the ./
prefix, working with arbitrary file names (many find
implementations including GNU find
choke on file names that are not valid text in the user's locale) and generally makes it easier and safer to work with the list of files if you need more than printing them.
Another solution is to use -regex
with those find
implementations that support it:
With GNU find
:
find -regex '.*\.i?ly'
# or the full command
find . -regextype posix-extended -regex '.*\.i?ly'
With BSD find
:
find -E . -regex '.*\.i?ly'
The -regex
option matches the whole path and is anchored at both start and end, so you need .*
at the beginning and don't need $
at the end.
?
is an extended regular expression operator (as in grep -E
) that matches 0 or 1 of the preceding atom, here i
. It's not available in basic regular expressions¹, so you need the -E
in BSD find
. In GNU find
(at least in current versions), the default regex are neither basic nor extended regex, but some regex variant from some ancient version of emacs, where ?
is supported. So that -regextype posix-extended
is not necessary in this case here.
¹ \{0,1\}
has been added to BREs as an equivalent of ERE ?
later though.
-
3
-
4use
.*\.i?ly$
rather than.*/.*\..?ly
../*/.*
can be reduced to just.*
(filenames output from find will always have a path),i?
restricts it to an optionali
after the.
rather than any character, and the$
anchors thely
to the end of the filename (otherwise it will match anywhere in the filename - e.g. it would match "i.can.fly.txt")– casMay 22 at 8:35 -