[comp.unix.questions] Deleting directories

ashish@janus.Berkeley.EDU (Ashish Mukharji) (07/10/90)

Recently, I had to remove all of a user's files older than a 
certain date.  That was easily accomplished with find(1), but deleting the 
resulting (empty) directory structure presents a greater problem.  The user's 
home directory is the root of a large, mostly empty directory tree.  I want
to delete all directories that do not contain any regular files - find starts
with . and works its way down (inorder).  What I need is a way to do a 
postorder traversal of the directory structure.  Is there a simple way, short 
of writing a C routine?

-ashish

Tuberculosis.  It's what they used to call consumption.
--------------------------------------------------------------------------
 . . !ucbvax!janus!ashish		  ashish%janus@ucbvax.BERKELEY.EDU
#43 Casa Zimbabwe    2422 Ridge Road   Berkeley CA 94709    (415) 549-4962

ecl@cbnewsj.att.com (Evelyn C. Leeper) (07/10/90)

In article <37481@ucbvax.BERKELEY.EDU> ashish@janus.Berkeley.EDU.UUCP (Ashish Mukharji) writes:
> Recently, I had to remove all of a user's files older than a 
> certain date.  That was easily accomplished with find(1), but deleting the 
> resulting (empty) directory structure presents a greater problem.  The user's 
> home directory is the root of a large, mostly empty directory tree.  I want
> to delete all directories that do not contain any regular files - find starts
> with . and works its way down (inorder).  What I need is a way to do a 
> postorder traversal of the directory structure.  Is there a simple way, short 
> of writing a C routine?

I should say RTFM, but:
	find top-directory-name -depth -type d -exec rmdir {} \;

The -depth goes postorder.
The rmdir will fail on any non-empty directories.

Evelyn C. Leeper  |  +1 201-957-2070  |  att!mtgzy!ecl or  ecl@mtgzy.att.com
--
The only thing necessary for the triumph of evil is for good men to do nothing. 
                                                            -Edmund Burke

tif@doorstop.austin.ibm.com (Paul Chamberlain) (07/11/90)

In article <37481@ucbvax.BERKELEY.EDU> ashish@janus.Berkeley.EDU.UUCP (Ashish Mukharji) writes:
>... but deleting the resulting (empty) directory structure presents
>a greater problem. ...

Isn't this what -depth does for find:

	find . -depth -type d -exec rmdir {} \;

I'd try this but "-depth" has absolutely no noticeable effect on my RT.

Paul Chamberlain | I do NOT represent IBM	  tif@doorstop, sc30661@ausvm6
512/838-7008	 | ...!cs.utexas.edu!ibmaus!auschs!doorstop.austin.ibm.com!tif

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (07/11/90)

In article <37481@ucbvax.BERKELEY.EDU> ashish@janus.Berkeley.EDU.UUCP (Ashish Mukharji) writes:
: Recently, I had to remove all of a user's files older than a 
: certain date.  That was easily accomplished with find(1), but deleting the 
: resulting (empty) directory structure presents a greater problem.  The user's 
: home directory is the root of a large, mostly empty directory tree.  I want
: to delete all directories that do not contain any regular files - find starts
: with . and works its way down (inorder).  What I need is a way to do a 
: postorder traversal of the directory structure.  Is there a simple way, short 
: of writing a C routine?

With regard to getting the directories in the right order, some find programs
have a -depth switch to do this.  Otherwise, pipe the output through sort -r.
Then you have to wrap something around to do the rmdir:

If there aren't too many:
    rmdir `find . -type d -print | sort -r`

If you have xargs:
    find . -type d -print | sort -r | xargs rmdir

If you have Perl:
    find . -type d -print | sort -r | perl -ne 'chop; rmdir;'

Using sh:
    find . -type d -print | sort -r | while read dir; do rmdir $dir; done

Using sed:
    find . -type d -print | sort -r | sed 's/^/rmdir /' | sh

With all but one of these, you'll have to ignore the error messages on
directories that can't be removed.  (Where ignoring may consist of >&/dev/null
or 2>/dev/null, depending on your culture (or lack thereof :-).)

The perl solution will be most efficient if you have the rmdir system call.
Otherwise the xargs solution will probably be best.

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov

davidsen@antarctica.crd.GE.COM (william E Davidsen) (07/11/90)

In article <1990Jul10.130548.10216@cbnewsj.att.com>, ecl@cbnewsj.att.com
(Evelyn C. Leeper) writes:

|> I should say RTFM, but:
|> 	find top-directory-name -depth -type d -exec rmdir {} \;
|> 
|> The -depth goes postorder.
|> The rmdir will fail on any non-empty directories.

  If you're on a machine with xargs it will go a LOT faster for big
trees if you say:

    find top-dir -type d -depth -print | xargs rmdir

  The suggested solution will work perfectly, but will run rmdir for
EVERY directory. xargs allows doing a bunch with each process.
--
Bill Davidsen (davidsen@crdos1.crd.ge.com, uunet!crdgw1!crdos1!davidsen)
  GE Corp R&D Center, Schenectady NY
  Moderator of comp.binaries.ibm.pc and 386users mailing list
"Stupidity, like virtue, is it's own reward" -me

A_DOUGHERTY@acc.haverford.edu (Andy Dougherty) (07/14/90)

... suggestions to use find -depth
Of course some versions of find do not have (or at least do not
document) the -depth option, so RTFM won't help.  In that case the
sort trick posted earlier will work.