I am using bash and rsync to create and store backups of my website. I am storing these in date folders of 'dd-mm-yyyy'.

I have been experimenting with the following to delete these folders if they are more than x days old (currently 2, but will be longer).

find /path/to/files -type d -mtime +2 -name [0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9] -exec rm -rf {} \; -prune

The above works, but just want to double check I'm not doing something glaringly wrong here.

I would then like to check if any folders were found, and if they were deleted, which ones.

I'm wondering if this would be as simple as something like the following to check if true:

if find /path/to/files -type d -mtime +2 -name [0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9] -exec rm -rf {} \; -prune; then

But then I am not sure how I would output the folder paths that were deleted.


find exits successfully whether it found files or not. Its definition of success is that the command line parameters are valid and there were no input/output errors. If you want to know whether it found some files, make it print something and check whether the output is non-empty.

If you want find to print the name of a file that it finds, insert -print as an action. You can chain multiple actions (e.g. -print, -exec and -prune just by putting them one after the other).

find /path/to/files -type d -mtime +2 -name '[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]' -print -exec rm -rf {} \; -prune

Note that you need quotes around the pattern passed to -name. Otherwise, if there happens to be a matching file in the current directory, the shell will expand that pattern before find sees it.

If you want to print the name of every deleted file and not just of the toplevel directory of each backup, and you're on Linux (more precisely, if you're using GNU coreutils), you can pass the -v flag to rm.

Note that the command you posted looks for matching directories everywhere under /path/to/files recursively, not just at the top level. I'm not sure if that's what you intended; for example, it would look inside recent backups. If you only want to match toplevel directories, the easiest way is to pass -maxdepth 1, and then you don't need -prune.

find /path/to/files -maxdepth 1 -type d -mtime +2 -name '[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]' -print -exec rm -rf {} \;

Alternatively, you can let the shell match directory names, and tell find never to recurse on anything by applying -prune before matching.

find /path/to/files/[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9] -prune -type d -mtime +2 -print -exec rm -rf {} \;

But this will result in an error if there are no files matching the pattern, or if there are so many matching files that their combined names overflow the maximum length of a command line. The -maxdepth approach doesn't have these defects.

If you want to log which files were deleted, redirect the output to a file.

  echo "# Deletions on $(date)"
  find /path/to/files -type d -mtime +2 -name '[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]' -print -exec rm -rf {} \; -prune
} >>backup-deletions.log

If you're worried about deleting the wrong thing, logging what you deleted would only let you know once it's too late. You could do a staged deletion by first moving things into a “trash can”, and emptying the trash can later.

# Move things to trash. Use whatever criteria you want.
find /path/to/files -type d -mtime +2 -name '[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]' -exec mv {} /path/to/trash \; -prune
# Delete directories from the trash can if they were moved more than
# a week ago.
find /path/to/trash -mindepth 1 -maxdepth 1 -ctime +7 -exec rm -rf {} \;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.