**
has no special meaning in find
patterns. -path '*/foo/*'
would find all files under a directory called foo
, including files in subdirectories. -path '*/foo/*' ! -path '*/foo/*/*'
would exclude files like a/foo/b/foo/c
. I don't think you can do this with just one invocation of POSIX find
.
With find
implementations that support -regex
(GNU, BusyBox, FreeBSD, NetBSD), you can use that to ensure that there's a single /
after foo
.
find . -regex '.*/foo/[^/]*' -type f
Alternatively, you can use find
to locate the foo
directories and a shell to enumerate files in this directory.
Another potential approach would be to invoke find
again, but I can't find a pure POSIX find
solution that actually works. With any POSIX find
, invoked again for each foo
directory:
find . -name foo -type d -exec find {} -type d ! -name foo -prune -o -type f \;
Beware that this mostly works, but not quite, and it's a little fragile. You need -type d -prune
to avoid recursing into subdirectories, but with just -type d -prune
, find would stop at the foo
directory. ! -name foo
does not prune foo/foo
, so a file like foo/foo/bar
will be reported twice. You can't use -exec
in the inner find
because its {}
would be interpreted by the outer find
. If your find
has -maxdepth
(which is being considered for inclusion in the next version of POSIX), you can make this reliable, but there's still this limitation against -exec
:
find . -name foo -type d -exec find {} -maxdepth 1 -type f \;
With any POSIX find and sh:
find . -name foo -type d -exec sh -c '
for x in "$0/"* "$0/".*; do
if [ -f "$x" ] && ! [ -L "$x" ]; then
…;
fi;
done
' {} \;
Substitute the code you want to run on the file names for …
.