之间写过一个讲文件备份到Amazon S3 的文章。 之后就有新的需求比如定期清理很久之前的备份(比如一个月前)。
Boto 库里面有一个s3put 的脚本,但是没有删除文件的脚本。 于是自己写了个s3del, 代码如下 。

#!/home/ftao/env/bin/python
# Copyright (c) 2010 Tao Fei http://ftao.org/
# Based on boto's s3put scirpt 
 
# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
import getopt, sys, os
import boto
from boto.exception import S3ResponseError
 
usage_string = """
SYNOPSIS
    s3del [-a/--access_key <access_key>] [-s/--secret_key <secret_key>]
          -b/--bucket <bucket_name> 
          [-d/--debug <debug_level>]
          [-n/--no_op] [-q/--quiet]
          path
 
    Where
        access_key - Your AWS Access Key ID.  If not supplied, boto will
                     use the value of the environment variable
                     AWS_ACCESS_KEY_ID
        secret_key - Your AWS Secret Access Key.  If not supplied, boto
                     will use the value of the environment variable
                     AWS_SECRET_ACCESS_KEY
        bucket_name - The name of the S3 bucket the file(s) should be
                      delete from.
        path - A path to a file or folder (must ends with '/') on s3 
        debug_level - 0 means no debug output (default), 1 means normal
                      debug output from boto, and 2 means boto debug output
                      plus request/response output from httplib
 
     If the -n option is provided, no files will be deleted from S3 but
     informational messages will be printed about what would happen.
"""
def usage():
    print usage_string
    sys.exit()
 
def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'a:b::d:hn:qs:v',
                                   ['access_key', 'bucket', 'debug', 'help', 
                                    'no_op', 'quiet', 'secret_key' ])
    except:
        usage()
    aws_access_key_id = None
    aws_secret_access_key = None
    bucket_name = ''
    debug = 
    quiet = False
    no_op = False
    for o, a in opts:
        if o in ('-h', '--help'):
            usage()
            sys.exit()
        if o in ('-a', '--access_key'):
            aws_access_key_id = a
        if o in ('-b', '--bucket'):
            bucket_name = a
        if o in ('-d', '--debug'):
            debug = int(a)
        if o in ('-n', '--no_op'):
            no_op = True
        if o in ('-q', '--quiet'):
            quiet = True
        if o in ('-s', '--secret_key'):
            aws_secret_access_key = a
    if len(args) != 1:
        usage()
    path = args[]
    if bucket_name:
        c = boto.connect_s3(aws_access_key_id=aws_access_key_id,
                            aws_secret_access_key=aws_secret_access_key)
        c.debug = debug
        b = c.get_bucket(bucket_name)
        keys = []
        #a folder 
        if path.endswith("/") and b.get_key(path) is None:
            for key in b.list():
                if key.name.startswith(path):
                    keys.append(key.name)
        else:
            keys = [path]
        for key in keys:
            print "remove " + key
            if not no_op:
                b.delete_key(key)
    else:
        usage()
 
if __name__ == "__main__":
    main()