4

I've this find script that finds files in the /home directory of more than 100 MB in size and deletes if it is more than 10 days old. It is scheduled for every day one time by cron job.

find /home/ -mtime +10 -type f -size +100M -delete >/dev/null 2>&1

Now, I want this script to remove directories recursively from where it removes files, as it is leaving empty directories.

Could anyone advise or suggest what change needs to be done in this script?

6

On a GNU system, you could do:

find /home/ -mtime +10 -type f -size +100M -delete -printf '%h\0' |
  awk -v RS='\0' '!seen[$0]++ {out = out $0 RS}
                  END {printf "%s", out}' |
  xargs -r0 rmdir

We use awk to filter out duplicate while still keeping the order (leaves before the branch they're on) and also delay the printing until all the files have been removed so rmdir can remove empty directories.

With zsh:

files=(/home/**/*(D.LM+100m+10od))
rm -f $files
rmdir ${(u)files:h}

Note that those would remove the directories that become empty after files are removed from them, but not the parent of those directories if they don't have any of those files to delete and become empty as a result of the directories being removed. If you want to remove those as well, with GNU rmdir, you can add the -p/--parents option to rmdir.

If you wanted to remove all empty directories regardless of whether files or directories have been removed from them or not, still with GNU find, you could do:

 find /home/ \( -mtime +10 -type f -size +100M -o -type d -empty \) -delete
  • Neither solution removes directories that become empty because their children were all directories that just got removed. – Gilles Mar 8 '17 at 23:32
  • @Gilles, good point. Answer updated. – Stéphane Chazelas Mar 9 '17 at 9:40
  • cd /home && find . -depth -mtime +10 -type f -size +100M -delete -o -type d -empty -delete – user218374 Mar 9 '17 at 10:43
  • @Rakesh, yes, though like for Philippos' answer, that would also delete directories that were empty beforehand. I've added a variant to the answer though, making the implications clear. – Stéphane Chazelas Mar 9 '17 at 10:52
2

Can't you remove all empty dirs in a second run afterwards (find option -empty along with -type d?

  • Nope. Try this: mkdir -p a/b/c; find . -type d -empty. You'd get back ./a/b/c, not ./a. – Satō Katsura Mar 8 '17 at 16:02
  • 1
    @SatoKatsura, find . -type d -empty -delete (which implies -depth) will delete them however. The problem here is that it would also delete directories that were already empty before. – Stéphane Chazelas Mar 8 '17 at 16:07
  • @StéphaneChazelas What about symlink loops? – Satō Katsura Mar 8 '17 at 16:08
  • 1
    @SatoKatsura, what about them? -type d doesn't select symlinks and without -L/-follow, find doesn't follow symlinks. – Stéphane Chazelas Mar 8 '17 at 16:10
0
cd "/home" && \
find . -depth -type d ! -name . ! -empty -exec sh -c '
   find "$1" -mtime +10 -type f -size +100M -delete
' {} {} \; -empty -delete

Summary

We need GNU find for the above to work. Basic idea being we invoke find with -depth mode which forces find to process child dirs earlier than their parents. Then we look at only dirs and only those that are nonempty thereby precluding find from deleting the originally empty dirs.

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.