2012-07-11 5 views

Répondre

33

Il existe aucun dossier dans S3. Au lieu de cela, les clés forment un espace de noms plat. Cependant, une clé avec des barres obliques dans son nom s'affiche spécialement dans certains programmes, y compris la console AWS (voir par exemple Amazon S3 boto - how to create a folder?). Au lieu de supprimer "un répertoire", vous pouvez (et devez) lister les fichiers par préfixe et supprimer. En substance:

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

Cependant, les autres réponses obtenues sur cette page présentent des approches plus efficaces.


Notez que le préfixe est juste recherché en utilisant la recherche par ficelle. Si le préfixe était your/directory, c'est-à-dire sans la barre oblique finale, le programme supprimerait également heureusement your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Pour plus d'informations, consultez S3 boto list keys sometimes returns directory key.

+0

Comment supprimer le répertoire? Si ce répertoire sera supprimé automatiquement lorsque tous les fichiers de ce répertoire sont supprimés? –

+0

Merci .. Je l'ai fini ~ –

+0

@wadehuang - pourriez-vous partager votre code sur la suppression des dossiers? – letsc

16

Vous pouvez utiliser bucket.delete_keys() avec une liste de clés (avec un grand nombre de clés que je trouve que cela soit un ordre de grandeur plus rapide que l'utilisation key.delete).

Quelque chose comme ceci:

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

Voir la solution de Patrick pour éviter les demandes N + 1 – deepelement

23

je pense que ça a été un moment et boto3 a plusieurs façons d'atteindre cet objectif. Cela suppose que vous souhaitez supprimer le test de « dossier » et tous ses objets est une façon ici:

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) 

Cela devrait faire deux demandes, l'une pour récupérer les objets dans le dossier, le second pour supprimer tous les objets dans ledit dossier.

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

+0

C'est de loin la solution la plus rapide. – deepelement

+0

C'est la solution la plus rapide, mais gardez à l'esprit que 'list_objects' ne peut pas retourner plus de 1000 clés, vous devez donc exécuter ce code plusieurs fois. – lampslave

+1

Vous pouvez utiliser paginator si vous avez plus de 1k objets - voir ma réponse ci-dessous. – dmitrybelyakov

6

Une légère amélioration par rapport à la solution de Patrick. Comme vous le savez peut-être, les deux list_objects() et delete_objects() ont une limite d'objet de 1000. C'est pourquoi vous devez paginer la liste et supprimer en morceaux. C'est assez universel et vous pouvez donner Prefix-paginator.paginate() pour supprimer les sous-répertoires/chemins

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) 
Questions connexes