I was confused as to why pruned directories were being printed by the
find command, too, and some other intricate details of how
-prune worked, but was able to figure it out with a few examples.
To run the examples below create the following directories and files.
To create this structure:
│ └── file1
│ └── file3
Now use find to look for directories named
aa. No problem here.
$ find . -type d -name aa
Look for all directories other than aa and we get the current directory
./bb, which also makes sense.
$ find . -type d ! -name aa
So far so good, but when we use
-prune, find returns the directory we are pruning, which initially confused me because I was expecting it to return all the other directories and not the one being pruned.
$ find . -type d -name aa -prune
The reason why it returns the directory being pruned is explained, not in the
-prune section of the man pages as indicated in Timo's answer, but in the
If the expression contains no actions other than
-print is performed on all files for which the expression is true.
which means that, since the expression matches the
aa directory name, then the expression will evaluate to true and it will be printed because find implicitly adds a
-print at the end of the entire command. It won't add a
-print, however, if you purposely add the action
-o -print to the end yourself:
find . -type d -name aa -prune -o -print
Here the find command DOES NOT add an implicit
-print anymore, and so the directory we are pruning (
aa) won't get printed.
So finally, if we add a clause that searches for files with a filename pattern of
file* after the
-o, then you have to put a
-print at the end of that second clause like this:
find . \( -type d -name aa -prune \) -o \( -type f -name 'file*' -print \)
The reason why this works is the same: If you don't put a
-print in the second clause, then since there is no action other than the
-prune action, find will add a
-print automatically at THE END of the command, causing the
-prune clause to print the pruned directory:
find . \( \( -type d -name aa -prune \) -o \( -type f -name 'file*' \) \) -print
In general, you need to place the
-print command in the second clause. If you place it in the middle like the original poster did, it will not work correctly because the files being pruned will be printed immediately and second clause will not get a chance to pick the files it wants:
find . \( -type d -name aa -prune -o -print \) -o \( -type f -name 'file*' \)
So unfortunately, the original poster got the command wrong above by placing the
-print in the wrong place. It might have worked for his specific case, but it doesn't work in the general case.
There are thousands of people who have difficulties understanding how
find man page should be updated in order to prevent the neverending worldwide confusion about this command.