Jonathan McKeown wrote:
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

Jonathan
_______________________________________________
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "freebsd-questions-unsubscr...@freebsd.org"

Thank you for this excellent answer! Now reading the man page begins to make sense.

Chris
_______________________________________________
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "freebsd-questions-unsubscr...@freebsd.org"

Reply via email to