Command line: piping find results to rm
UnixCommand LineFindRmUnix Problem Overview
I'm trying to work out a command which deletes sql files older than 15 days.
The find part is working but not the rm.
rm -f | find -L /usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups -type f \( -name '*.sql' \) -mtime +15
It kicks out a list of exactly the files I want deleted but is not deleting them. The paths are correct.
usage: rm [-f | -i] [-dIPRrvW] file ...
unlink file
/usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/20120601.backup.sql
...
/usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/20120610.backup.sql
What am I doing wrong?
Unix Solutions
Solution 1 - Unix
You are actually piping rm
's output to the input of find
. What you want is to use the output of find
as arguments to rm
:
find -type f -name '*.sql' -mtime +15 | xargs rm
xargs
is the command that "converts" its standard input into arguments of another program, or, as they more accurately put it on the man
page,
> build and execute command lines from standard input
Note that if file names can contain whitespace characters, you should correct for that:
find -type f -name '*.sql' -mtime +15 -print0 | xargs -0 rm
But actually, find
has a shortcut for this: the -delete
option:
find -type f -name '*.sql' -mtime +15 -delete
Please be aware of the following warnings in man find
:
Warnings: Don't forget that the find command line is evaluated
as an expression, so putting -delete first will make find try to
delete everything below the starting points you specified. When
testing a find command line that you later intend to use with
-delete, you should explicitly specify -depth in order to avoid
later surprises. Because -delete implies -depth, you cannot
usefully use -prune and -delete together.
P.S. Note that piping directly to rm
isn't an option, because rm
doesn't expect filenames on standard input. What you are currently doing is piping them backwards.
Solution 2 - Unix
find /usr/www/bar/htdocs -mtime +15 -exec rm {} \;
Will select files in /usr/www/bar/htdocs
older than 15 days and remove them.
Solution 3 - Unix
Another simpler method is to use locate
command. Then, pipe the result to xargs
.
For example,
locate file | xargs rm
Solution 4 - Unix
Assuming you aren't in the directory containing the *.sql backup files:
find /usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/*.sql -mtime +15 -exec rm -v {} \;
The -v option above is handy it will verbosely output which files are being deleted as they are removed.
I like to list the files that will be deleted first to be sure. E.g:
find /usr/www2/bar/htdocs/foo/rsync/httpdocs/db_backups/*.sql -mtime +15 -exec ls -lrth {} \;
Solution 5 - Unix
Use xargs to pass arguments, with the option -rd '\n' to ignore spaces in names:
> "${command}" | xargs -rd '\n' rm
Include --force if you want to also remove read only files.