For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > July 2006 > I can't get the hang of the -prune option of find.









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author I can't get the hang of the -prune option of find.
spibou@gmail.com

2006-07-17, 7:00 pm

Despite several experiments I still can't quite understand how
the -prune option of find works. So can someone give me some
examples ? Assume that I want to omit directories dir1 , dir2 ,
dir3. How should I write the find command ?

Spiros Bousbouras

Eric Sosman

2006-07-17, 7:00 pm



spibou@gmail.com wrote On 07/17/06 16:03,:
> Despite several experiments I still can't quite understand how
> the -prune option of find works. So can someone give me some
> examples ? Assume that I want to omit directories dir1 , dir2 ,
> dir3. How should I write the find command ?


find foo \( -type d -name dir\[123\] -prune \) -o -type f -print

This lists all the regular files in the foo hierarchy,
excluding any descendants of directories named dir1, dir2,
or dir3. Note that the exclusion applies at all containment
levels: foo/dir1/* and foo/bar/dir2/* and foo/bar/baz/dir3/*
are all excluded.

--
Eric.Sosman@sun.com

spibou@gmail.com

2006-07-17, 7:00 pm


Eric Sosman wrote:

> spibou@gmail.com wrote On 07/17/06 16:03,:
>
> find foo \( -type d -name dir\[123\] -prune \) -o -type f -print
>
> This lists all the regular files in the foo hierarchy,
> excluding any descendants of directories named dir1, dir2,
> or dir3. Note that the exclusion applies at all containment
> levels: foo/dir1/* and foo/bar/dir2/* and foo/bar/baz/dir3/*
> are all excluded.


Hmmm , the general principle still eludes me. The way I read
the above command is

Print all files below foo which
satisfy \( -type d -name dir\[123\] -prune \)
or
are regular files

So this should print all regular files. I mean -o is the or operator,
right ? It seems to me that if you want to omit some files *and*
print the rest, you should use the -a flag. However a bit of experi-
mentation shows that your construction is correct and does what
is supposed to do. So what am I missing ?

Is it necessary to include -print in the command you gave ?
Can you rewrite the example giving the 3 directory names
explicitly ie without using the dir\[123\] shorthand ?

Eric Sosman

2006-07-17, 7:00 pm



spibou@gmail.com wrote On 07/17/06 17:02,:
> Eric Sosman wrote:
>
>
>
>
> Hmmm , the general principle still eludes me. The way I read
> the above command is
>
> Print all files below foo which
> satisfy \( -type d -name dir\[123\] -prune \)
> or
> are regular files
>
> So this should print all regular files. I mean -o is the or operator,
> right ? It seems to me that if you want to omit some files *and*
> print the rest, you should use the -a flag. However a bit of experi-
> mentation shows that your construction is correct and does what
> is supposed to do. So what am I missing ?


The special effect of -prune, which is "don't pursue
this branch any further." So when -type d declares "This
is a directory" and -name dir\[123\] days "with the name
dir1, dir2, or dir3," the -prune says "don't search inside
this directory." The search never enters the excluded
directory so its contents are never even looked at, much
less handed to the stuff after -o.

> Is it necessary to include -print in the command you gave ?


I don't know. In early versions of find, it certainly
was: without some kind of action (-print, -exec, ...), find
would just locate the files and do nothing. Later, some find
variants were enhanced to supply an implicit -print if no
other action was specified, but I've never bothered to find
out whether this enhancement was ever standardized or has
become widespread. I know what I want find to do with the
files it locates, and I'm not shy about telling it.

> Can you rewrite the example giving the 3 directory names
> explicitly ie without using the dir\[123\] shorthand ?


Untested:

find foo \( -type d \( -name ford -o -name arthur \
-o -name zaphod \) \
-prune \) \
-o type f -print

Like APL programs, find commands can be "write-only."

--
Eric.Sosman@sun.com

Barry Margolin

2006-07-17, 9:59 pm

In article <1153170155.963687.173460@p79g2000cwp.googlegroups.com>,
"spibou@gmail.com" <spibou@gmail.com> wrote:

> Eric Sosman wrote:
>
>
> Hmmm , the general principle still eludes me. The way I read
> the above command is
>
> Print all files below foo which
> satisfy \( -type d -name dir\[123\] -prune \)
> or
> are regular files


No, the -print option is only applied to the second branch of the -o.
The first branch, which contains the -prune, does not contain -print, so
nothing is printed for files that match that branch.

>
> Is it necessary to include -print in the command you gave ?


I don't think so. If there are no action options anywhere in the
command, the default is to assume -print at the very end.

> Can you rewrite the example giving the 3 directory names
> explicitly ie without using the dir\[123\] shorthand ?


Replace -name dir\[123\] with \( -name dir1 -o -name dir2 -o -name dir3
\)

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Logan Shaw

2006-07-19, 4:00 am

spibou@gmail.com wrote:
> Eric Sosman wrote:
>
>
> Hmmm , the general principle still eludes me. The way I read
> the above command is
>
> Print all files below foo which
> satisfy \( -type d -name dir\[123\] -prune \)
> or
> are regular files


It's a lazy "or", like C's "||" operator.

Lazy "or" (and "and") operators, although they have a truth value,
also act like conditionals. So this C code:

foo() || bar();

has a program flow like this:

if (!foo())
bar();

In the above, bar() is only executed if foo() is false. You
don't need to execute bar() if foo() evaluates to true, because
"True OR X" is true regardless of whether X is true or false.

Likewise, this C code:

foo() && bar();

has a program flow like this:

if (foo()) { bar(); }

and for similar reasons.

Getting back to the "find" command, the last several arguments
also form an expression:

-name 'dir[123]' -prune
-o
-type f -print

This can be further expanded since the first two tests ("-name"
and "-prune") and the last two tests ("-type" and "-print") have
an implied "and" between them, making the above equivalent to
this (parenthesized to indicate order of operations -- yes, "find"
does apply precedence rules and doesn't just evaluate left to
right):

( -name 'dir[123]' -a -prune )
-o
( -type f -a -print )

Now, "-prune" and "-print" are tests, but they are tests in a
bit of a degenerate way, because they always pass. Their purpose
is only to have side effects. So, the lazy operators will have
a program flow like this:

if name matches 'dir[123]'
then
prune
else
if type is 'f'
then
print
endif
endif

Hope that helps.

- Logan
spibou@gmail.com

2006-07-20, 4:01 am

Thanks everyone , I believe I've got it now.

Spiros Bousbouras

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com