[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Auto-emptying of trash.



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

Attachment: signature.asc
Description: Digital signature


Reply to: