On Friday 06 February 2009 02:55, Chris Whitehouse wrote:
> I think you should be able to do it with a combination of -prune and
> -delete (or -exec rm -rf {} \; ) on a find command. Substitute your
> other commands for rm -rf in the -exec above.
> I would give you a working example except I can't figure out the syntax
> for -prune. Examples from google don't seem to work in (my) FreeBSD.

[skip to the end for a simple answer without the lengthy exposition]

find(1) can be confusing, especially if you think of the ``actions'' 
( -print, -exec and -delete plus their variants like -ls and -ok ) as 
something different from the ``tests'' ( -name and so on), or if you don't 
take account of the evaluation order.

A find expression comprises a number of what the manpage calls primaries, each 
of which evaluates as true or false. (It may also have a side-effect, 
like -print whose side-effect is to print the name). Primaries can be 
combined with -and (which is usually implied) or -or. Where -and and -or both 
occur, find will group the -anded primaries together before evaluation. 
Taking one of your examples below,

find . -print -or -prune -name dir1

this is grouped as

find . -print -or \( -prune -and -name dir1 \)

find will then evaluate the whole expression from left to right for each 
pathname in the tree it's looking at, stopping within each set of (implied) 
parentheses and within the overall expression as soon as it can determine 
truth or falsehood. (This is what's referred to in programming as 
short-circuiting in boolean expressions).

If primaries are linked by -and, find can stop at the first one that's false, 
knowing the expression is false; if they're linked by -or it can stop at the 
first one that's true, knowing the expression is true. Otherwise it has to 
evaluate the whole expression.

Before it does this, though, find checks for side-effects. If there isn't a 
side-effect anywhere in your expression, find will put brackets round the 
whole expression and a -print after it.

Looking at your examples:

> chr...@pcbsd% find .

(No expression). Find adds a -print, so this is the same as the next one:

> chr...@pcbsd% find . -print
> .
> ./test.mov
> ./test.mpg
> ./dir1
> ./dir1/file1
> ./dir1/file2
> ./file3

-print is always true so the expression is true for each name - they get 
printed as a side-effect.

> chr...@pcbsd% find . -print -o -prune dir1
> find: dir1: unknown option

-prune doesn't take an argument, so dir1 is a syntax error.

> chr...@pcbsd% find . -print -o -prune -name dir1

find evaluates the print, which prints each name as its side-effect. -print 
evaluates as true. Since it's in an -or, find can stop there, so it never 
sees the second expression ( -prune -and -name dir1: the -and is implicit).
> .
> ./test.mov
> ./test.mpg
> ./dir1
> ./dir1/file1
> ./dir1/file2
> ./file3

> chr...@pcbsd% find . -print -o -name dir1 -prune

Same again: find stops after the -print which is always true, and ignores 
the -name dir1 -and -prune.

> chr...@pcbsd% find . -name "*" -o -name dir1 -prune

None of these primaries has a side-effect, so find rewrites this internally as

find . \( -name "*" -or -name dir1 -prune \) -print

-name "*" is always true, so find can ignore everything after the -or up to 
the parenthesis. Because the first expression is true, and the parens are 
followed by (an implied) -and, find has to evaluate the -print, which is 
always true, so the whole expression is always true and it always prints the 
name as a side-effect.
> .
> ./test.mov
> ./test.mpg
> ./dir1
> ./dir1/file1
> ./dir1/file2
> ./file3

What you need is an expression with two outcomes: a -prune for some names and 
a -print for others. That tells you you need an -or, and the -print must come 
after it because it's always true. Before the -or, -prune is always true so 
you need some sort of testing primary before the -prune.

That gives you

find . -name dir1 -prune -or -print

freebsd-questions@freebsd.org mailing list
To unsubscribe, send any mail to "freebsd-questions-unsubscr...@freebsd.org"

Reply via email to