Fun Scripting Problem

Giorgos Keramidas keramida at FreeBSD.org
Fri Feb 15 17:03:42 UTC 2013


On 2013-02-13 12:27, Tim Daneliuk <tundra at tundraware.com> wrote:
> I know how to do this in Python, but I really want to do it in
> straight Bourne shell.  I have some ideas, but I thought I'd
> give you folks a crack at this Big Fun:
>
> a)  You have a directory of files - say they're logs - generated
>     at nondeterministic intervals.  You may get more than one a day,
>     more than one a month, none, or hundreds.
>
> b) To conserve space, you want to keep the last file generated
>    in any given month (the archive goes back for an unspecified
>    number of years), and delete all the files generated prior to
>    that last file in that same month.
>
> c) Bonus points if the problem is solved generally for either files
>    or directories generated as described above.
>
> These are not actually logs, and no, I don't think logrotate can
> do this ... or can it?

You can try using stat/date to print the month in which each file was
modified, e.g:

    freefall:/home/keramida$ stat -f '%m %N' prs.tar.bz2
    1359910210 prs.tar.bz2

    freefall:/home/keramida$ date -f '%s' -j '1359910210' '+%Y-%m'
    2013-02

Having the mtime of the file in seconds since the epoch (1359910210)
should be easy to sort through, e.g. you can find the last modification
time with a 'sort -n | tail -1' pipe:

    freefall:/home/keramida/w/doc-head/el_GR.ISO8859-7/share$ touch xml/glossary.ent

    freefall:/home/keramida/w/doc-head/el_GR.ISO8859-7/share$ find xml -exec stat -f '%m %N' {} +
    1360060289 xml
    1360060288 xml/navibar.l10n.ent
    1360060288 xml/trademarks.ent
    1360060288 xml/libcommon.xsl
    1360060288 xml/header.l10n.ent
 => 1360942284 xml/glossary.ent
    1360060289 xml/freebsd.dsl
    1360060289 xml/teams.ent
    1360060289 xml/freebsd.ent
    1360060289 xml/l10n.ent
    1360060289 xml/mailing-lists.ent
    1360060289 xml/newsgroups.ent
    1360060289 xml/translators.ent
    1360060289 xml/catalog.xml
    1360060289 xml/entities.ent
    1360060289 xml/catalog
    1360060289 xml/urls.ent

    freefall:/home/keramida/w/doc-head/el_GR.ISO8859-7/share$ find xml -exec stat -f '%m %N' {} + | sort -n | tail -1
    1360942284 xml/glossary.ent

Then you can convert the epoch-based times to '%Y-%m' timestamps in a
loop, e.g.:

freefall:/home/keramida/w/doc-head/el_GR.ISO8859-7/share$ find xml \
> -exec stat -f '%m %N' {} + | while read mtime fname ; do
>     echo ${mtime} $( date -f '%s' -j "${mtime}" '+%Y-%m' ) ${fname}
> done
1360060289 2013-02 xml
1360060288 2013-02 xml/navibar.l10n.ent
1360060288 2013-02 xml/trademarks.ent
1360060288 2013-02 xml/libcommon.xsl
1360060288 2013-02 xml/header.l10n.ent
1360942284 2013-02 xml/glossary.ent
1360060289 2013-02 xml/freebsd.dsl
1360060289 2013-02 xml/teams.ent
1360060289 2013-02 xml/freebsd.ent
1360060289 2013-02 xml/l10n.ent
1360060289 2013-02 xml/mailing-lists.ent
1360060289 2013-02 xml/newsgroups.ent
1360060289 2013-02 xml/translators.ent
1360060289 2013-02 xml/catalog.xml
1360060289 2013-02 xml/entities.ent
1360060289 2013-02 xml/catalog
1360060289 2013-02 xml/urls.ent

Having the mtime in seconds as the first column is still conducive to
sorting / tail:

freefall:/home/keramida/w/doc-head/el_GR.ISO8859-7/share$ find xml \
> -exec stat -f '%m %N' {} + | while read mtime fname ; do
>      echo ${mtime} $( date -f '%s' -j "${mtime}" '+%Y-%m' ) ${fname};
> done | sort -n | tail -1
1360942284 2013-02 xml/glossary.ent

>From that point it should be trivial to select all files whose timestamp
is smaller than or equal to 1360942284 - one month of seconds.



More information about the freebsd-questions mailing list