Shell – difference between results and effectiveness after adding -f in rm and -print in find

shell-scriptxargs

I got a task to delete all files which are older than 90 days from /dir/prd/log recrusively i.e delete from subdirectries too. I made this command:

find /dir/prd/log* -mtime +90 | xargs rm

Then I was talking to a unix guy and he suggested

find /dir/prd/log* -mtime +90 -print | xargs rm -f

I just want to know what would have been his purpose to put "-print" and "-f" in command.

Best Answer

-f tells rm to never prompt (e.g. when it encounters read-only files) and to ignore missing files it’s asked to delete (instead of indicating an error). It will also not complain if not passed any file to remove.

Here, depending on the xargs implementation rm's stdin will be either the pipe from find or /dev/null, so without -f, find may end up reading the answer to those prompts from the output of find!

-print is the default action for find in Linux distributions and POSIX-compliant systems, but might need to be explicitly specified on very old Unix or Unix-like systems.

So his purpose was probably to make the command more robust and portable. You could do better with some variants of find (going beyond POSIX):

find /dir/prd/log -mtime +90 -print0 | xargs -0 rm -f

avoids problems with filenames containing “special” characters (including space, newline, tab, single quote, double quote, backslash), and if your find supports the -delete action,

find /dir/prd/log -mtime +90 -delete

avoids spawning other processes to perform the deletion (and also avoids some race condition issues). (Note that I’m specifying /dir/prd/log here to match your stated requirement from the first sentence of your question, as confirmed in the comments.)

With POSIX find, you can still avoid xargs and filename parsing by asking find to run rm itself:

find /dir/prd/log -mtime +90 -exec rm -f '{}' +

Beside being more portable and reliable, it also avoids the issue of rm reading prompt answers from find's output mentioned above (it also avoids running rm at all if no file is found).

If /dir/prod/log contains subdirectories, you’ll want to filter them to avoid error messages since rm can’t delete them:

find /dir/prd/log ! -type d -mtime +90 -exec rm -f '{}' +
Related Question