I am trying to remove all empty files that are older than 2 days. Also I am ignoring hidden files, starting with dot. I am doing it with this code:
find /u01/ -type f -size 0 -print -mtime +2 | grep -v "/\\." | xargs rm
It works fine until there are spaces in the name of the file. How could I make my code ignore them?
OS is Solaris.
Install GNU find
and GNU xargs
in an appropriate location (not /usr/bin
) and use:
find /u01/ -type f -size 0 -mtime +2 -name '[!.]*' -print0 | xargs -0 rm
(Note that I removed (what I think is) a stray -print
from your find
options. The options shown removes empty files modified more than 2 days ago where the name does not start with a .
, which is the condition that your original grep
seemed to deal with.)
The problem is primarily that xargs
is defined to split its input at spaces. An alternative is to write your own xargs
surrogate that behaves sensibly with spaces in names; I've done that. You then only run into problems if the file names contain newlines — which the file system allows. Using a NUL ('\0'
) terminator is guaranteed safe; it is the only character that can't appear in a path name (which is why GNU chose to use it with -print0
etc).
A final better option is perhaps:
find /u01/ -type f -size 0 -mtime +2 -name '[!.]*' -exec rm {} \;
This avoids using xargs
at all and handles all file names (path names) correctly — at the cost of executing rm
once for each file found. That's not too painful if you're only dealing with a few files on each run.
POSIX 2008 introduces the notation +
in place of the \;
and then behaves rather like xargs
, collecting as many arguments as will conveniently fit in the space it allocates for the command line before running the command:
find /u01/ -type f -size 0 -mtime +2 -name '[!.]*' -exec rm {} +
The versions of Solaris I've worked on do not support that notation, but I know I work on antique versions of Solaris. GNU find
does support the +
marker and therefore renders the -print0
and xargs -0
workaround unnecessary.