Sharon Kimble wrote: > I'm trying to get a bash script working from a cron job that will empty > trash of all files and directories that are older than $N [7 days in > this case]. This partly works but is very inefficient in that it > doesn't delete everything that is available to be deleted, just tends > to leave stuff with no apparent reasoning.
Very likely you are running into the problem that removing files from the directory causes the directory to be updated. Because the directory is updated it ceases to be old enough to be aged off. This leaves them around until they become old enough to be an age candidate again. Let's walk through the problem step by step. > #!/bin/bash Since there are no bash features I suggest using /bin/sh the standard shell. Others would say "use bash features". :-) I like standard better. A preference. > # emptyTrash.sh The use of a .sh on the end is frowned upon. Sure it is a shell script at this instant. But you actually have a bash script and so it should be called .bash instead of .sh. But next week you might want to convert it to a perl script. Two weeks after that you might want to convert it to a python script. Or Ruby. Encoding the language in the extension then gets in the way. It isn't needed. If your editor is a smart one, and most are these days, then it doesn't need the extension to know how to syntax highlight it. > for SUBDIR in files info > do > echo Lookin\' in Trash/${SUBDIR}... > find ${HOME}/.local/share/Trash/$SUBDIR -mtime +${DAYS} -exec rm -vrf {} > \; done Running 'find' and 'for' is inconsistent. The 'find' command can do both. I would have it do both. The "\;" part is the classic old legacy way of running find's -exec. It runs one argument per command. That is less efficient than running as many arguments as possible. The new (ten years old is still new) way to do this and POSIX standard is using "+". Using "+" will stack as many arguments as possible and is very efficient. Let's start by printing the entries and then work from there. find $HOME/.local/share/Trash -mtime +$DAYS -print Files and directories. I would like to remove only the files first. find $HOME/.local/share/Trash -type f -mtime +$DAYS -print I would like find to remove them itself. The -delete option was added to GNU find some years ago and is available in all current GNU systems. # Warning: This fires the -delete option and will delete those files! find $HOME/.local/share/Trash -type f -mtime +$DAYS -delete The files are gone. Directories may be left behind. I would like to remove the directories as a second pass. find $HOME/.local/share/Trash -type d -print Looks good. Let's remove those too. But I am likely to avoid looking to see if a directory should be removed and simply try to remove it and deal with the non-empty errors. These are not files and were only created because the files were put there. No need to look at mtime on the trash directories. Just "rmdir" any empty directory. Using "rmdir" is very safe because it cannot remove files. The "rmdir" can only remove empty directories making it a quite safe command to simply fling out without looking. Can only remove directories from the bottom up so turn on -depth. find $HOME/.local/share/Trash -depth -type d -exec rmdir {} + ...may have some errors about non-empty directories... Looking better. But if a directory is not empty the GNU rmdir command has an option specifically for it. Let's ignore only that case. find $HOME/.local/share/Trash -depth -type d -exec rmdir --ignore-fail-on-non-empty {} + And there we have the components for this type of cleanup the way I would do them. (Others would undoubtedly prefer a different way. There is more than one way to do this.) And so we are left with these two commands run one after the other to do the full clean up. #!/bin/sh # emptyTrash DAYS=7 # retain for N days find $HOME/.local/share/Trash -type f -mtime +$DAYS -delete find $HOME/.local/share/Trash -depth -type d -exec rmdir --ignore-fail-on-non-empty {} + Hope that helps. Bob
signature.asc
Description: Digital signature