Amazon S3 boto - как удалить папку?

Я создал папку в s3 с именем «test» и вставил «test_1.jpg», «test_2.jpg» в «test».

Как я могу использовать boto для удаления папки "test"?


person wade huang    schedule 11.07.2012    source источник
comment
@pyCthon Неправильная технология. Попробуйте снова.   -  person devinbost    schedule 16.01.2019


Ответы (8)


В S3 нет папок. Вместо этого ключи образуют плоское пространство имен. Однако ключ с косой чертой в названии отображается в некоторых программах, включая консоль AWS (см., Например, Amazon S3 boto - как создать папку?).

Вместо удаления «каталога» вы можете (и должны) перечислять файлы по префиксу и удалять. По сути:

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

Однако в других завершенных ответах на этой странице представлены более эффективные подходы.


Обратите внимание, что префикс просто ищется с помощью поиска по фиктивной строке. Если бы префикс был your/directory, то есть без добавленной косой черты, программа также успешно удалила бы your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Для получения дополнительной информации см. Ключи списка ботинок S3 иногда возвращают ключ каталога.

person Antti Haapala    schedule 11.07.2012
comment
Как удалить каталог? Если этот каталог будет удален автоматически при удалении всех файлов в этом каталоге? - person wade huang; 11.07.2012
comment
Спасибо .. Я закончил ~ - person wade huang; 11.07.2012
comment
@wadehuang - не могли бы вы поделиться своим кодом об удалении папок? - person letsc; 18.03.2015
comment
Как удалить файлы в папке s3, которым 2 дня в python. есть это в моем s3 - bucket / 1 / backups / (10 файлов) необходимо удалить все файлы, которым два дня - person 艾瑪艾瑪艾瑪; 29.07.2019

Вот версия 2018 (почти 2019):

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
person Raz    schedule 18.12.2018
comment
Это, безусловно, лучший ответ. - person user554481; 05.02.2019
comment
кому-то может быть полезно узнать, что bucket.objects.all (). delete () очищает все ведро, не удаляя его, независимо от количества объектов (т.е. это не влияет, кроме ограничения в 1000 элементов). См. boto3.amazonaws. com / v1 / documentation / api / latest / reference / - person fabiog; 09.12.2019
comment
Привет, Раз, это не работает для меня, я просто получаю пустые квадратные скобки, то есть [] - person Soyf; 11.12.2019
comment
К сожалению, это не поддерживает суффикс :( - person Anum Sheraz; 06.05.2020
comment
Самое замечательное, что это решение работает даже с более чем 1000 объектами. - person Mabyn; 15.09.2020
comment
Если вам нужно указать идентификатор и секрет ключа доступа, первая строка: s3 = boto3.resource ('s3', aws_access_key_id = xxx, aws_secret_access_key = yyy) - person Douglas Daly; 29.09.2020
comment
@raz Если возможно, не могли бы вы обновить ответ, чтобы отразить / распечатать то, что удаляется, и выйти из программы, если срок действия токена истечет? Сейчас это работает хорошо, но нет возможности узнать, что удаляется и что происходит, так как у меня только мигающий курсор - person DJ_Stuffy_K; 19.12.2020

Я чувствую, что прошло много времени, и у boto3 есть несколько различных способов достижения этой цели. Предполагается, что вы хотите удалить "папку" test и все ее объекты. Вот один из способов:

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)

Это должно сделать два запроса: один для извлечения объектов в папке, второй для удаления всех объектов в указанной папке.

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

person Patrick    schedule 19.01.2016
comment
Это, безусловно, самое быстрое решение. - person deepelement; 23.01.2016
comment
Это самое быстрое решение, но имейте в виду, что list_objects не может вернуть более 1000 ключей, поэтому вам нужно запускать этот код несколько раз. - person lampslave; 19.04.2016
comment
Вы можете использовать пагинатор, если у вас более 1k объектов - см. Мой ответ ниже. - person dmitrybelyakov; 16.04.2017
comment
@deepelement, и он работает только в boto3, но не в boto - person avocado; 11.09.2017
comment
Это отлично работает, и вы можете запустить его из лямбда-выражения Python, поместив приведенный выше код в функцию lambda_handler: import boto3; def lambda_handler(event, context): '''Code from above'''. Убедитесь, что вы даете Lambda разрешение на удаление из S3 и продлите время ожидания. - person Nadir Sidi; 27.07.2018

Вы можете использовать bucket.delete_keys () со списком ключей (я обнаружил, что с большим количеством ключей это на порядок быстрее, чем при использовании key.delete).

Что-то вроде этого:

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)
person David Fooks    schedule 11.04.2013

Небольшое улучшение решения Патрика. Как вы, возможно, знаете, и list_objects(), и delete_objects() имеют ограничение на количество объектов 1000. Вот почему вы должны разбивать список на страницы и удалять по частям. Это довольно универсально, и вы можете передать Prefix paginator.paginate() для удаления подкаталогов / путей

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)
person dmitrybelyakov    schedule 16.04.2017
comment
А если вы хотите ограничиться каталогом, используйте ключевое слово Prefix в paginator.paginate() См. Все параметры: boto3.readthedocs.io/en/latest/reference/services/ - person Chad; 05.06.2018
comment
с фильтром Prefix, предложенным @Chad, мне пришлось добавить if item is not None проверку перед удалением (поскольку некоторые из моих префиксов S3 не существовали / не имели объектов) - person y2k-shubham; 24.09.2019
comment
@dmitraybelyakov, когда я запускаю приведенный выше код, я получаю Typeerror: объект 'NoneType' не подлежит написанию в следующей строке delete_us ['Objects']. append (dict (key = item ['Key'])) знаете ли вы какие-либо причина, почему это должно было сделать это - person Aaron; 16.06.2021
comment
@Aaron, возможно, что-то изменилось, но попробуйте предложение выше y2k-shubham - person dmitrybelyakov; 16.06.2021

Если для сегмента S3 включено управление версиями:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
person Dan-Dev    schedule 05.08.2020
comment
Есть ли способ распечатать то, что удаляется? Я хочу сначала удалить версии, а затем текущую. ex bucket.objects.filter (Префикс = myprefix /). delete (); сейчас я вижу только мигающий курсор и не знаю, что происходит. - person DJ_Stuffy_K; 10.12.2020
comment
Вам нужно будет сделать что-то вроде files_to_delete = bucket.object_versions.filter(Prefix="myprefix/"), затем перебрать files_to_delete и вызвать для них print (), а затем delete (). - person Dan-Dev; 10.12.2020

Если нужно фильтровать по содержимому объекта, как это сделал я, следующая схема вашей логики:

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})
person Boris    schedule 16.12.2020

person    schedule
comment
Вы должны исправить отступы в коде. - person Danizavtz; 14.05.2021