I need to invoke find on a set of "starting points" which is generated, but
some of paths may not be valid:
paths() {
#
# mock version of the generator
#
echo /bin
echo kjsdfhk
echo /etc
}
find $(paths) -type f name foo.sh
My problem is that I don't know if the path will be valid and if it's not, I want to silently ignore it. Easiest for me is now
paths \
| while read path;
do
test -e "$path" || continue
find "$path" -type f -name foo.sh
done
but this is expensive: it invokes find for each valid path, and since the whole code may be called inside loop, I'd like to find a more effective way.
One easy and very unix-y solution would be to have find read the "starting points" from STDIN:
paths \
| while read path;
do
test -e "$path" || continue
done \
| find - -type f -name foo.sh
except that… find does not support this! 🙂
Any ideas?
Note that the paths are provided by user, so spaces (and probably other funny things) need to be considered. Also I'm aiming for POSIX /bin/sh
but that could be sacrificed. (Oh, and sinking whole STDERR to /dev/null
is not an option either…)
Update: Sorry, I forgot to mention that I'm restricted to bash—I probably confused it more by the POSIX note. Actually the code is looking for snippets to source inside Bash scripts and is now mostly in sh with few bashisms that I might get rid of in future version. So if I could avoid putting more bashisms in, that would be cool but I certainly can't afford "zshisms", however elegant — as @stephane's answer (go vote it up now!).
Best Answer
In
zsh
, if you have the paths in an array as in:(which would split the output of
paths
on space, tab newline or nul) or:to split on lines, you can do:
Or if you want to restrict to directories:
Now, if none of those files exist, you may end up running:
Which with some
find
implementations like GNU's means searching in the current directory. To avoid that, you could do:Or:
Now, with
zsh
, there's no real need forfind
here, you could simply do:That would also have the benefit to work even if those files are like
!
or-name
whichfind
would choke on.There's a difference though in the case where those files are symlinks to directories (
find
would not look for files in them, whilezsh
would (which may actually be what you want)).