find -L . \
\( -type d \
\( -path "*/ignore" -o -path "*/indeed" -o \
\( -path "*/subdir/*" ! -path "*/subdir/save" \
\) \
\) \
\) \
-prune -o -print
If you want extra filter (like -name "*.ext") you have to put that right before -print. The last part then looks like this
-prune -o \( -name "*.ext" \) -print
Note that I changed the names for easier writeability and readability. Names starting with i are to be ignored. Names starting with s are to be shown. Names ending in file are files.
My tree looks like this:
$ find -printf "%y %p\n"
d .
d ./base
d ./base/subdir
d ./base/subdir/inform
f ./base/subdir/inform/imagefile
d ./base/subdir/isolate
f ./base/subdir/isolate/individualfile
f ./base/subdir/whatwhatinthefile
d ./base/subdir/save
f ./base/subdir/save/soundfile
f ./base/superfile
d ./base/indeed
f ./base/indeed/itemfile
d ./base/show
f ./base/show/startfile
d ./base/ignore
f ./base/ignore/importantfile
The output of the above command:
.
./base
./base/subdir
./base/subdir/whatwhatinthefile
./base/subdir/save
./base/subdir/save/soundfile
./base/superfile
./base/show
./base/show/startfile
Note that whatwhatinthefile in base/subdir. If you do not want the files in base/subdir then you have to exlude them explicitly. I tried but the command line became too ugly.
Depending on your use case it might be easier to define a shell function like this:
contrivedfind() {
find -L . \
\( -type d \
\( -path "*/ignore" -o -path "*/indeed" -o -path "*/subdir" \
\) \
\) \
-prune -o -print
find -L ./base/subdir/save
}
Output is now:
.
./base
./base/superfile
./base/show
./base/show/startfile
./base/subdir/save
./base/subdir/save/soundfile
The only other thing different from before now is the missing ./base/subdir entry. But I think that does not matter in your case because you want to filter for files anyway.
As before you have to put any extra filter before the -print in the first find and this time also at the end of the second find.