[NTLUG:Discuss] rm doesn't recurse

Steve Baker sjbaker1 at airmail.net
Fri May 7 09:35:42 CDT 2004


Kenneth Loafman wrote:

> I like the rm -r method myself.  Since its recursive, it does not expand 
> all the arguments to the command line.  I have run across cases where 
> expanding the find blows the command line length out of the water.

No!  There *isn't* an "rm -r" method.  If you say:

    rm -r *.zip

...then what will happen is:

1) The shell will search for all files in the current directory
    that match the '*.zip' pattern.  Now we have something like:

    rm -r a.zip b.zip c.zip

2) rm now starts running.  It has NO IDEA that there was a wildcard
    on the command line.

3) rm says - OK look through my list of arguments - and remove each
    one recursively (because of the '-r').

4) None of the command line arguments are directories - so it just
    removes those three zip files and doesn't look into any sub-directories.

What ever approach you take, SOMETHING has to search through the directories
beneath this one, finding files that match some pattern.

The tool that has historically been responsible for searching through piles
of directories matching patterns (dates, access rights, ownership, file type,
etc) is 'find'.

So - all good solutions to doing this are going to entail calling 'find'.

There are perhaps three ways to take the results of 'find' and to pass them
to 'rm'.

1) You can put the find command between back-quotes (`).  This tells the shell
    to run the command between the back-quotes and replace that command with the
    results of running it.

    eg:
       rm `find . -name \*.zip`

    You are correct in saying that this is A BAD IDEA because there is a hard
    limit on the maximum size of a shell command line (I think it's 10k bytes
    or so).   If the combined lengths of the file names of all those zip files
    exceeds 10k (don't forget the spaces between them)...then you'll get a shell
    error.

    So - back-quote methods *suck*.

2) You could redirect the results of find into another command's standard input.
    However, 'rm' doesn't have an option to take the list of files from the command
    line.  There is a program (xargs) that can take a list of files on standard input
    and convert it to a list.

    eg:
       find . -name \*.zip | xargs rm {}

    This is a perfectly good solution - as 'find' produces matching filenames, it
    passes them to xargs which runs the 'rm' command with that file as it's argument.

3) Fortunately, the designers of the 'find' program thought of this.  There is an
    option to 'find' that works much like 'xargs' - but saves using a pipe and an
    extra command:

    eg:

       find . -name \*.zip -exec rm {}

The 'for' loop solution that someone posted earlier is a type (1) solution because
it puts the 'find' command into back-quotes.

---------------------------- Steve Baker -------------------------
HomeEmail: <sjbaker1 at airmail.net>    WorkEmail: <sjbaker at link.com>
HomePage : http://www.sjbaker.org
Projects : http://plib.sf.net    http://tuxaqfh.sf.net
            http://tuxkart.sf.net http://prettypoly.sf.net
-----BEGIN GEEK CODE BLOCK-----
GCS d-- s:+ a+ C++++$ UL+++$ P--- L++++$ E--- W+++ N o+ K? w--- !O M-
V-- PS++ PE- Y-- PGP-- t+ 5 X R+++ tv b++ DI++ D G+ e++ h--(-) r+++ y++++
-----END GEEK CODE BLOCK-----



More information about the Discuss mailing list