2012-07-11 11 views

Odpowiedz

33

W folderze S3 znajdują się foldery no. Zamiast tego klucze tworzą płaską przestrzeń nazw. Jednak klucz z ukośnikami w nazwie pokazuje się szczególnie w niektórych programach, w tym w konsoli AWS (patrz na przykład Amazon S3 boto - how to create a folder?).

Zamiast usuwać "katalog", możesz (i musisz) wystawiać pliki według prefiksu i usuwać. W istocie:

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

Jednak pozostałe znakomitymi odpowiedzi na tej stronie cechą bardziej efektywnych rozwiązań.


Zauważ, że przedrostek jest właśnie przeszukiwany za pomocą atrapowego wyszukiwania ciągów. Jeśli przedrostek był your/directory, tj. Bez dołączonego końcowego slasha, program również z przyjemnością usuwałby your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Aby uzyskać więcej informacji, zobacz S3 boto list keys sometimes returns directory key.

+0

Jak usunąć katalog? Czy ten katalog zostanie usunięty automatycznie po usunięciu wszystkich plików z tego katalogu? –

+0

Dziękuję .. Skończyłem to ~ –

+0

@wadehuang - czy mógłbyś udostępnić swój kod na temat usuwania folderów? – letsc

16

Można użyć bucket.delete_keys() listę kluczy (z dużą ilością klawiszy Znalazłem to być o rząd wielkości szybciej niż przy użyciu 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) 
+0

Zobacz rozwiązanie Patricka, aby uniknąć zgłoszeń N + 1 – deepelement

23

czuję, że minęło trochę czasu i boto3 ma kilka różnych sposobów osiągnięcia tego celu. Zakłada się, że chcesz usunąć test„folder” i wszystkich jego obiektów 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) 

ten powinien zrobić dwa wnioski, jeden do pobierania obiektów w folderze, drugi, aby usunąć wszystkie obiekty we wspomnianym folderze.

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

+0

Jest to zdecydowanie najszybsze rozwiązanie. – deepelement

+0

To jest najszybsze rozwiązanie, ale należy pamiętać, że 'list_objects' nie może zwrócić więcej niż 1000 kluczy, więc musisz uruchomić ten kod wiele razy. – lampslave

+1

Możesz użyć paginatora, jeśli masz więcej niż 1k obiektów - zobacz moją odpowiedź poniżej. – dmitrybelyakov

6

Nieznaczna poprawa na rozwiązanie Patryka. Jak pewnie wiecie, zarówno list_objects() jak i delete_objects() mają limit obiektów 1000. Dlatego też musisz podzielić strony na strony i usuwać w częściach. To jest dość powszechne i można dać Prefix do paginator.paginate() usunąć podkatalogi/ścieżki

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)