Amazon S3 boto – how to delete folder?

Question:

I created a folder in s3 named “test” and I pushed “test_1.jpg”, “test_2.jpg” into “test”.

How can I use boto to delete folder “test”?

Asked By: wade huang

||

Answers:

There are no folders in S3. Instead, the keys form a flat namespace. However a key with slashes in its name shows specially in some programs, including the AWS console (see for example Amazon S3 boto – how to create a folder?).

Instead of deleting "a directory", you can (and have to) list files by prefix and delete. In essence:

for key in bucket.list(prefix='your/directory/'):
    key.delete()

However the other accomplished answers on this page feature more efficient approaches.


Notice that the prefix is just searched using dummy string search. If the prefix were your/directory, that is, without the trailing slash appended, the program would also happily delete your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

For more information, see S3 boto list keys sometimes returns directory key.

You can use bucket.delete_keys() with a list of keys (with a large number of keys I found this to be an order of magnitude faster than using key.delete).

Something like this:

delete_key_list = []
for key in bucket.list(prefix='/your/directory/'):
    delete_key_list.append(key)
    if len(delete_key_list) > 100:
        bucket.delete_keys(delete_key_list)
        delete_key_list = []

if len(delete_key_list) > 0:
    bucket.delete_keys(delete_key_list)
Answered By: David Fooks

I feel that it’s been a while and boto3 has a few different ways of accomplishing this goal. This assumes you want to delete the test “folder” and all of its objects Here is one way:

s3 = boto3.resource('s3')
objects_to_delete = s3.meta.client.list_objects(Bucket="MyBucket", Prefix="myfolder/test/")

delete_keys = {'Objects' : []}
delete_keys['Objects'] = [{'Key' : k} for k in [obj['Key'] for obj in objects_to_delete.get('Contents', [])]]

s3.meta.client.delete_objects(Bucket="MyBucket", Delete=delete_keys)

This should make two requests, one to fetch the objects in the folder, the second to delete all objects in said folder.

https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects

Answered By: Patrick

A slight improvement on Patrick’s solution. As you might know, both list_objects() and delete_objects() have an object limit of 1000. This is why you have to paginate listing and delete in chunks. This is pretty universal and you can give Prefix to paginator.paginate() to delete subdirectories/paths

client = boto3.client('s3', **credentials)
paginator = client.get_paginator('list_objects_v2')
pages = paginator.paginate(Bucket=self.bucket_name)

delete_us = dict(Objects=[])
for item in pages.search('Contents'):
    delete_us['Objects'].append(dict(Key=item['Key']))

    # flush once aws limit reached
    if len(delete_us['Objects']) >= 1000:
        client.delete_objects(Bucket=bucket, Delete=delete_us)
        delete_us = dict(Objects=[])

# flush rest
if len(delete_us['Objects']):
    client.delete_objects(Bucket=bucket, Delete=delete_us)
Answered By: dmitrybelyakov

Here is 2018 (almost 2019) version:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Answered By: Raz

If versioning is enabled on the S3 bucket:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
Answered By: Dan-Dev

If one needs to filter by object contents like I did, the following is a blueprint for your logic:

def get_s3_objects_batches(s3: S3Client, **base_kwargs):
    kwargs = dict(MaxKeys=1000, **base_kwargs)
    while True:
        response = s3.list_objects_v2(**kwargs)
        # to yield each and every file: yield from response.get('Contents', [])
        yield response.get('Contents', [])
        if not response.get('IsTruncated'):  # At the end of the list?
            break
        continuation_token = response.get('NextContinuationToken')
        kwargs['ContinuationToken'] = continuation_token


def your_filter(b):
   raise NotImplementedError()


session = boto3.session.Session(profile_name=profile_name)
s3client = session.client('s3')
for batch in get_s3_objects_batches(s3client, Bucket=bucket_name, Prefix=prefix):
    to_delete = [{'Key': obj['Key']} for obj in batch if your_filter(obj)]
    if to_delete:
        s3client.delete_objects(Bucket=bucket_name, Delete={'Objects': to_delete})
Answered By: Boris

#Deleting a Files Inside Folder S3 using boto3#

def delete_from_minio():
    """
    This function is used to delete files or folder inside the another Folder
    """
    try:
        logger.info("Deleting from minio")
        aws_access_key_id='Your_aws_acess_key'
        aws_secret_access_key = 'Your_aws_Secret_key'
        host = 'your_aws_endpoint'
        s3 = boto3.resource('s3', aws_access_key_id=aws_access_key_id,
                            aws_secret_access_key=aws_secret_access_key ,
                            config=boto3.session.Config(signature_version='your_version'),
                            region_name="your_region",
                            endpoint_url=host ,
                            verify=False)
        bucket = s3.Bucket('Your_bucket_name')
        for obj in bucket.objects.filter(Prefix='Directory/Sub_Directory'):
            s3.Object(bucket.name, obj.key).delete()
    except Exception as e:
        print(f"Error Occurred while deleting from the S3,{str(e)}")

Hope this Helps 🙂

Answered By: Sanju Jayachandran