I have few files under the current directory,
./a.txt
./b.txt
./dir1/c.txt
./dir1/d.txt
When I execute find . -path './dir1' -prune -o -name "*.txt"
,
as expected, it excludes everything under ‘dir1’ and prints,
./a.txt
./b.txt
./dir1
now if I switch the sequence of the subexpression and execute find . -name "*.txt" -o -path './dir1' -prune
,
to my understanding, it should have displayed all the files, as -name "*.txt"
subexpression should have matched everything that has .txt extension and just or
them with the following test. Therefore ‘dir1’ directory contents should not have been excluded. But that’s doesn’t seem to be the case. Displayed result is same as the previous one.
./a.txt
./b.txt
./dir1
what am I missing here?
My system is ubuntu-20.04. I have skim through the find man page and couldn’t find any solution.
Other sources in the web didn’t provide with any satisfactory explanation either.
3
Answers
To be honest, in 40+ years of shell programming I don’t think I’ve never used the
-prune
option forfind
as I find (no pun intended) it too confusing and so end up restricting my search path or discarding unwanted results in other ways.In general, though,
A or B
=B or A
, e.g. "I want a cat or a dog" = "I want a dog or a cat", so when "A" =-path './dir1' -prune
, "B" =-name "*.txt"
and "or" =-o
, these are equivalent:-path './dir1' -prune
) or (-o
) B (-name "*.txt"
)-name "*.txt"
) or (-o
) A (-path './dir1' -prune
)The
-o
is not applied in a complete run offind
(ie, ‘do all the things on the LH side of-o
and if nothing is found then do the RH side…)Instead the
-o
is file by file which is a big difference. Essentially you have this loop:print
)The other thing going on here is no combination of
-o
‘s or-a
‘s or parenthesis will overcome that-prune
has the highest precedence — if a directory is listed with-prune
it is never visited.If you want to do something along these lines:
Then Bash is probably your best bet. Something along these lines:
You are assuming
-prune
means "do not show this entry".Instead,
-prune
means "do not descend into this directory".Your top level directory contains the following:
If you use
-prune
when you encounter./dir1
, thenfind
will not descend into it and therefore never look at./dir1/c.txt
or./dir1/d.txt
.