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”?


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.


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()

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


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)

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)

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()
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.