I'm trying to find files or folders in a directory based on different conditions :
- all files that start with a W or,
- all the files ending with an X or,
- all files starting with Y and ending with Z!.
This has been my best bet so far :
find -name 'w*' || find -name '*x' || 'find -name 'y*' & find -name '*z!'
Which isn't working obviously. No error messages obviously, just that it doesn't find all the files I'm looking for.
CodePudding user response:
You can specify multiple predicates with -o
to OR them.
find -name 'w*' -o -name '*x' -o -name 'y*z'
Equivalently, you can use a single -regex
which captures all these conditions.
find -regex '.*/\(w[^/]*\|[^/]*x\|y[^/]*z\)'
(Notice how the argument to -regex
is applied to the entire path, and how the regex syntax out of the box requires backslashes in some weird places compared to most modern regex dialects. Obviously, regex is different from regular wildcards; in a regular expression, .*
matches any string, and [^/]*
matches a sequence of characters which mustn't be a slash. The regex syntax here works with GNU find
but not e.g. MacOS / BSD find
; try adding an -E
option and removing the backslashes before (
, |
, and )
.)
It's not clear what you hope ||
would do. It would run the second find
if the first failed, but it won't (unless you give it invalid predicates or something; not finding any files is not an error).
Even more bewilderingly, &
runs the job in the background; you were probably looking for &&
, but it also doesn't do what you want. What you tried could be done very inefficiently simply with
find -name 'w*'
find -name '*x'
find -name 'y*z'
though the repeated traversals could possibly report the same file more than once. But you want to avoid that and only traverse the directory tree once, as that can be a very heavy operation.