|
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:19 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:19 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:19 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:19 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-18, 1:20 am |
| 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, 1:23 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, 7:51 am |
| Thanks everyone , I believe I've got it now.
Spiros Bousbouras
|
|
|
|
|