in reply to Re: UNIX command - remove 0 byte file
in thread UNIX command - remove 0 byte file

find /whatever/path/ -size 0 -exec rm {} \;
One comment. "-exec" is generally not the best idea unless you care that your command is executed on exactly one file at a time. The problem with exec is that it spawns a new process for every file that it finds. Which isn't bad if the process takes a long time; the tiem spent in starting a new process is shadowed by the run time of the executable. However, in the case of rm, the operation is very quick, so the converse is true.

In this case, we have a couple of options. In looking at my local find man page, I see that find has a -delete option. This may be a Linux-ism though, as I don't seem to remember this on Solaris. Failing that, we always have xargs. And so, your invocation becomes either find . -size 0 -delete or find . -size 0 | xargs rm. I've seen the xargs version speed up an invocation of find by roughly an order of magnitude. YMMV.

thor

Feel the white light, the light within
Be your own disciple, fan the sparks of will
For all of us waiting, your kingdom will come

Replies are listed 'Best First'.
Re^3: UNIX command - remove 0 byte file
by Moron (Curate) on Sep 23, 2005 at 12:33 UTC
    -delete is indeed a linuxism as opposed to a unix option of find, but xargs is indeed available under e.g. Solaris.

    A potential problem with using xargs is that although it means only one execution of rm which bodes better performance, it also converts everything read in from the pipe into a single argument list, which above a certain limit will cause rm to Segmentation Fault, whereas -exec is guaranteed to work for an unlimited number of files. The choice therefore depends on the particular environment it is being applied to.

    -M

    Free your mind

      A potential problem with using xargs is that although it means only one execution of rm which bodes better performance, it also converts everything read in from the pipe into a single argument list

      No, it doesn't. xargs is smart enough that it knows the system limits, and splits of the task into several processes if needed. That's the beauty of xargs.

      $ find /opt/perl -print0 2> /dev/null | xargs -0 | wc -l 42 $
      Split up into 42 calls to /bin/echo (the default for xargs). Note also the use of -print0 and -0, that eliminates problems with filenames containing whitespace.
        Note also the use of -print0 and -0, that eliminates problems with filenames containing whitespace.
        I think that those are Linux-only features as well. I sure like them when I can use them, though. :)

        thor

        Feel the white light, the light within
        Be your own disciple, fan the sparks of will
        For all of us waiting, your kingdom will come

        Let's not forget the OP specifically said 'unix' rather than linux. Filenames with whitespace not being handled with xargs is certainly going to be a problem if this is supposed to be a generic solution. But if the whole file is enclosed in quotes when it has whitespace, rm will handle the argument list properly even if it went thru xargs:
        find /path/ -size 0 | perl -e 'while(<>) { chop; s/^(.*\s.*)$/\"$1\"/; + print "$_\n"; }' | xargs -n <whatever-filecount-limit> rm

        -M

        Free your mind

        I looked into this for xargs under Solaris and the manual makes no such claim, although it looks like you can do something similar manually using a combination of -l -s and -n options, assuming you know the system limits to target these parameters for.

        -M

        Free your mind

      Actually, xargs is supposed to handle that. It will break the command line when it gets too long (1024 words, I think) and run the command again.

      But the most annoying thing with xargs is that it doesn't handle spaces or other special characters well:

      server:~> ls a file server:~> ls | xargs rm a: No such file or directory file: No such file or directory
      You're forced to do tricks with sed (or perl -e) to get this to work.
        GNU xargs offers -i to deal with spaces.

        ls | xargs -i ls
        XargFoo