Paperclip Bob
Paperclip Bob

Reputation: 386

Leaving out '-print' from 'find' command when '-prune' is used

I have never been able to fully understand the -prune action of the find command. But in actuality at least some of my misunderstanding stems from the effect of omitting the '-print' expression.

From the 'find' man page..

"If the expression contains no actions other than -prune, -print is performed on all files for which the expression is true."

.. which I have always (for many years) taken to mean I can leave out '-print'.

However, as the following example illustrates, there is a difference between using '-print' and omitting '-print', at least when a '-prune' expression appears.

First of all, I have the following 8 directories under my working directory..

aqua/
aqua/blue/
blue/
blue/orange/
blue/red/
cyan/blue/
green/
green/yellow/

There are a total of 10 files in those 8 directories..

aqua/blue/config.txt
aqua/config.txt
blue/config.txt
blue/orange/config.txt
blue/red/config.txt
cyan/blue/config.txt
green/config.txt
green/test.log
green/yellow/config.txt
green/yellow/test.log

My goal is to use 'find' to display all regular files not having 'blue' as part of the file's path. There are five files matching this requirement.

This works as expected..

% find . -path '*blue*' -prune -o -type f -print
./green/test.log
./green/yellow/config.txt
./green/yellow/test.log
./green/config.txt
./aqua/config.txt

But when I leave out '-print' it returns not only the five desired files, but also any directory whose path name contains 'blue'..

% find . -path '*blue*' -prune -o -type f
./green/test.log
./green/yellow/config.txt
./green/yellow/test.log
./green/config.txt
./cyan/blue
./blue
./aqua/blue
./aqua/config.txt

So why are the three 'blue' directories displayed?

This can be significant because often I'm trying to prune out a directory structure that contains more than 50,000 files. When that path is processed my find command, especially if I'm doing an '-exec grep' to each file, can take a huge amount of time processing files for which I have absolutely no interest. I need to have confidence that find is not going into the pruned structure.

Upvotes: 6

Views: 791

Answers (1)

ephemient
ephemient

Reputation: 204698

The implicit -print applies to the entire expression, not just the last part of it.

% find . \( -path '*blue*' -prune -o -type f \) -print
./green/test.log
./green/yellow/config.txt
./green/yellow/test.log
./green/config.txt
./cyan/blue
./blue
./aqua/blue
./aqua/config.txt

It's not decending into the pruned directories, but it is printing out the top level.

A slight modification:

$ find . ! \( -path '*blue*' -prune \) -type f
./green/test.log
./green/yellow/config.txt
./green/yellow/test.log
./green/config.txt
./aqua/config.txt

(with implicit -a) would lead to having the same behavior with and without -print.

Upvotes: 2

Related Questions