Amazon S3 boto - jak usunąć folder?

87

Utworzyłem folder w s3 o nazwie „test” i wrzuciłem „test_1.jpg”, „test_2.jpg” do „test”.

Jak mogę użyć boto, aby usunąć folder „test”?

wade huang
źródło
1
@pyCthon Zła technologia. Spróbuj ponownie.
devinbost

Odpowiedzi:

61

W S3 nie ma żadnych folderów. Zamiast tego klucze tworzą płaską przestrzeń nazw. Jednak klucz ze ukośnikami w nazwie pojawia się szczególnie w niektórych programach, w tym w konsoli AWS (zobacz na przykład boto Amazon S3 - jak utworzyć folder? ).

Zamiast usuwać „katalog”, możesz (i musisz) wyświetlać pliki według prefiksu i usuwać. W istocie:

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

Jednak inne osiągnięte odpowiedzi na tej stronie zawierają bardziej wydajne podejścia.


Zwróć uwagę, że przedrostek jest po prostu przeszukiwany przy użyciu fikcyjnego wyszukiwania ciągów. Gdyby prefiks był your/directory, to znaczy bez dodanego końcowego ukośnika, program również zostałby szczęśliwie usunięty your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Aby uzyskać więcej informacji, zobacz Klawisze listy boto S3 czasami zwracają klucz katalogu.

Antti Haapala
źródło
1
Jak usunąć katalog? Czy ten katalog zostanie usunięty automatycznie po usunięciu wszystkich plików w tym katalogu?
wade huang
Dziękuję .. Skończyłem to ~
wade huang
@wadehuang - czy mógłbyś udostępnić swój kod dotyczący usuwania folderów?
Letsc
Jak usunąć pliki w folderze s3, które mają 2 dni w Pythonie. mam to w moim s3 - bucket / 1 / backups / (10 plików) trzeba usunąć wszystkie pliki
sprzed
190

Oto wersja 2018 (prawie 2019):

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Raz
źródło
23
To zdecydowanie najlepsza odpowiedź.
user554481
1
ktoś może się przydać, aby wiedzieć, że bucket.objects.all (). delete () opróżnia cały zasobnik bez usuwania go, bez względu na to, ile jest obiektów (tj. nie ma na to wpływu, ale limit 1000 elementów). Zobacz: boto3.amazonaws.com/v1/documentation/api/latest/reference/…
fabiog
1
Cześć Raz, to nie działa dla mnie, po prostu widzę puste nawiasy kwadratowe, tj. []
Soyf
Niestety, nie obsługuje to Suffix :(
Anum Sheraz
Wspaniałe jest to, że to rozwiązanie działa nawet z ponad 1000 obiektów
Mabyn
45

Czuję, że minęło trochę czasu i boto3 ma kilka różnych sposobów na osiągnięcie tego celu. Zakładamy, że chcesz usunąć testowy „folder” i wszystkie jego obiekty. Oto jeden sposób:

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)

Powinno to spowodować dwa żądania, jedno o pobranie obiektów z folderu, a drugie o usunięcie wszystkich obiektów w tym folderze.

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

Patrick
źródło
To zdecydowanie najszybsze rozwiązanie.
deepelement
2
To najszybsze rozwiązanie, ale pamiętaj, że list_objectsnie może zwrócić więcej niż 1000 kluczy, więc musisz wielokrotnie uruchamiać ten kod.
lampaslave
4
Możesz użyć paginatora, jeśli masz więcej niż 1k obiektów - zobacz moją odpowiedź poniżej.
dmitrybelyakov
@deepelement, i działa tylko w boto3, a nie boto
awokado,
1
Działa to doskonale, a można go uruchomić z lambda Python umieszczając powyższy kod w funkcji lambda_handler: import boto3; def lambda_handler(event, context): '''Code from above'''. Upewnij się, że pozwoliłeś swojej Lambdzie usunąć z S3 i przedłużyć limit czasu.
Nadir Sidi
21

Możesz użyć bucket.delete_keys () z listą kluczy (przy dużej liczbie kluczy okazało się, że jest to o rząd wielkości szybsze niż użycie key.delete).

Coś takiego:

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)
David Fooks
źródło
20

Niewielka poprawa w stosunku do rozwiązania Patricka. Jak być może wiesz, oba list_objects()i delete_objects()mają limit liczby obiektów wynoszący 1000. Dlatego musisz dzielić listę i usuwać w fragmentach. To jest dość powszechne i można dać Prefixsię paginator.paginate()aby usunąć podkatalogach / ścieżek

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)
dmitrybelyakov
źródło
2
A jeśli chcesz ograniczyć się do „katalogu”, użyj Prefixsłowa kluczowego w paginator.paginate()sekcji Zobacz wszystkie opcje: boto3.readthedocs.io/en/latest/reference/services/ ...
Czad
1
z Prefixfiltrem zasugerowanym przez @Chad musiałem dodać if item is not Noneczek przed usunięciem (ponieważ niektóre z moich prefiksów S3 nie istniały / nie miały obiektów)
y2k-shubham
1

Jeśli przechowywanie wersji jest włączone w zasobniku S3:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
Dan-Dev
źródło