[comp.unix.questions] 'find' - can i prune on the basis of pathnames?

klm@cme-durer.ARPA (Ken Manheimer) (05/09/88)

I have what ought to be a simple thing to do using find that actually
seems to be beyond its capabilities.  Can anyone out there reveal
something i've overlooked?

First of all, i'm dealing with the /usr/bin/find of Sun OS 3.5.  The
problem concerns pruning absolute paths from a directory-structure
traversal. This is as opposed to pruning relative directory-names,
which is easy to do using a '-name <dirname> -prune' clause.  The
problem is that i have only been successful using a <dirname> that has
*no* path components (slashes).  It's pretty clear to me, both from
the wording in the man page (the fact that the -name argument is
specified to take a 'filename' qualifier, rather than a 'pathname')
and from the behavior, that in fact the -name argument will not accept
pathnames, and i can't see any other way to accomplish what i want
using find.

Here's an example to illustrate:

given directory structure:

       /usr/local/testdir/
	     /     \
     firstSub	    secondSub	(/usr/local/testdir/{first,second}sub/)
      /  \	      /	    \
firstOne firstTwo secondOne secondTwo	(leaf files)

Then commands (with any embedded narrative comments in square brackets'[]':)

				-=-

% cd /usr/local/testdir
% find . -print
.
./first
./first/firstOne
./first/firstTwo
./second
./second/secondOne
./second/secondTwo

[now prune out contents of second, by specifying a '-print' and-ed
 with a -prune for the file named 'second':] 

% find . -print -name second -prune
.
./first
./first/firstOne
./first/firstTwo
./second

[That works fine.
 Now, a few attempts to prune matching on more elaborate pathnames for second:]

% find . -print -name ./second -prune
.
./first
./first/firstOne
./first/firstTwo
./second
./second/secondOne
./second/secondTwo
% find /usr/local/testdir -print -name /usr/local/testdir/second -prune
/usr/local/testdir
/usr/local/testdir/first
/usr/local/testdir/first/firstOne
/usr/local/testdir/first/firstTwo
/usr/local/testdir/second
/usr/local/testdir/second/secondOne
/usr/local/testdir/second/secondTwo

				-=-

In case it's relevant, i'm doing all this to obtain a stream of
filenames for input to a backup archiver.  I'm already using the
-name/-prune feature to bypass the contents of archetypal dirnames
such as 'spool', 'tmp', and 'dev', but would like a way to prune
out some of the parts of the standard sun distribution, such as
'/usr.MC68020', without risk eg of pruning a users directory that
they happened to name similarly ('/usr2/someone/stuff/usr.MC68020/').

Is it in fact the case that find will not perform a prune on the basis
of a (non-trivial) pathname, or am i missing something essential?  I
know i could accomplish what i want using a post-filter, eg grep
family, of the find output, but i am reluctant to do so for a few
reasons, and in any event i'd like to be sure about how to properly
use find.

Thin kew in advance for any help,

Ken Manheimer		 klm@cme-durer.ARPA or ..!uunet!cme-durer.arpa!klm
National Bureau of Standards, Factory Automation System, Software Support

A man must have chaos within him to give birth to a dancing star  - Nietzsche

chris@mimsy.UUCP (Chris Torek) (05/10/88)

In article <435@stylus.cme-durer.ARPA> klm@cme-durer.ARPA (Ken Manheimer)
writes:
>... The problem concerns pruning absolute paths from a directory-structure
>traversal. This is as opposed to pruning relative directory-names,
>which is easy to do using a '-name <dirname> -prune' clause.

It cannot be done directly.  You *can* do this:

  find <path> -exec expr {} = /foo/bar \| {} = /foo/baz \; -prune -o <pred>

This will not perform <pred> on /foo/bar and /foo/baz; if you want them
done, but not any files within them, try

  find <path> \( -exec expr <exprs> \; ! -prune \) -o <pred>

>Is it in fact the case that find will not perform a prune on the basis
>of a (non-trivial) pathname...?

It is.  -prune simply says `do not search the current path any deeper',
and then succeeds a la -print.  (At least, that is what the one I put
in on our Vaxen does, and I did it from the Sun documentation.)

>... I know i could accomplish what i want using a post-filter ...

That would probably be fastest.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (05/11/88)

Considering your application, you can get there from here by
  find . -name foo -print | egrep -v '\./name1|\./name1/" > file

The problem is that -prune only looks at the current filename
(basename). Therefore the name xxx is omitted from the output, but names
of the format xxx/anything will not be. I do much the same thing, and
drop anything with the string "/tmp/" in the name.
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me