Amazon S3 boto - como excluir uma pasta?

87

Eu criei uma pasta no s3 chamada "test" e coloquei "test_1.jpg", "test_2.jpg" em "test".

Como posso usar o boto para deletar a pasta "teste"?

wade huang
fonte
1
@pyCthon Tecnologia errada. Tente novamente.
devinbost de

Respostas:

61

Não pastas no S3. Em vez disso, as chaves formam um namespace simples. No entanto, uma chave com barras em seu nome é exibida especialmente em alguns programas, incluindo o console AWS (consulte por exemplo Amazon S3 boto - como criar uma pasta? ).

Em vez de excluir "um diretório", você pode (e deve) listar arquivos por prefixo e excluir. Em essência:

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

No entanto, as outras respostas concluídas nesta página apresentam abordagens mais eficientes.


Observe que o prefixo é pesquisado apenas usando a pesquisa de string fictícia. Se o prefixo fosse your/directory, ou seja, sem a barra final anexada, o programa também o excluiria your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Para obter mais informações, consulte S3 boto list keys às vezes retorna a chave de diretório.

Antti Haapala
fonte
1
Como deletar o diretório? Se este diretório for excluído automaticamente quando todos os arquivos neste diretório forem excluídos?
wade huang
Obrigado .. Eu terminei ~
wade huang
@wadehuang - você poderia compartilhar seu código sobre exclusão de pastas?
letc
Como deletar arquivos na pasta de s3 que têm 2 dias em python. tenho isso em meu s3 - bucket / 1 / backups / (10 arquivos) preciso remover todos os arquivos que têm dois dias
艾瑪艾瑪 艾瑪
186

Aqui está a versão 2018 (quase 2019):

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Raz
fonte
22
Esta é de longe a melhor resposta.
user554481
1
alguém pode achar útil saber que bucket.objects.all (). delete () esvazia todo o bucket sem excluí-lo, não importa quantos objetos existam (ou seja, não é afetado, mas o limite de 1000 itens). Consulte: boto3.amazonaws.com/v1/documentation/api/latest/reference/…
fabiog
1
Olá, Raz, isso não está funcionando para mim. Simplesmente recebo colchetes vazios, ou seja, []
Soyf
Infelizmente, isso não é compatível com o sufixo :(
Anum Sheraz
O bom é que essa solução funciona mesmo com mais de 1000 objetos
Mabyn
45

Eu sinto que já faz um tempo e o boto3 tem algumas maneiras diferentes de atingir esse objetivo. Isso pressupõe que você deseja excluir a "pasta" de teste e todos os seus objetos. Aqui está uma maneira:

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)

Isso deve fazer duas solicitações, uma para buscar os objetos da pasta e a segunda para excluir todos os objetos dessa pasta.

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

Patrick
fonte
Esta é de longe a solução mais rápida.
deepelement
2
Essa é a solução mais rápida, mas lembre-se de que list_objectsnão pode retornar mais de 1000 chaves, portanto, você precisa executar esse código várias vezes.
lampião de
4
Você pode usar o paginator se tiver mais de 1k objetos - veja minha resposta abaixo.
dmitrybelyakov
@deepelement, e só funciona em boto3, não boto
abacate
1
Isso funciona muito bem, e você pode executá-lo a partir de um lambda Python, colocando o código acima em uma função lambda_handler: import boto3; def lambda_handler(event, context): '''Code from above'''. Certifique-se de dar permissão ao seu Lambda para excluir do S3 e estender o tempo limite.
Nadir Sidi
21

Você pode usar bucket.delete_keys () com uma lista de chaves (com um grande número de chaves, achei isso uma ordem de magnitude mais rápido do que usar key.delete).

Algo assim:

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
fonte
20

Uma ligeira melhora na solução de Patrick. Como você deve saber, ambos list_objects()e delete_objects()têm um limite de objeto de 1000. É por isso que você deve paginar a listagem e excluir em pedaços. Isso é muito universal e você pode dar Prefixpara paginator.paginate()a subdiretórios apagar / caminhos

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
fonte
2
E se você quiser limitar a um "diretório", use a Prefixpalavra - chave em paginator.paginate()Ver todas as opções: boto3.readthedocs.io/en/latest/reference/services/…
Chade
1
com o Prefixfiltro sugerido por @Chad , eu tive que adicionar uma if item is not Noneverificação antes da exclusão (já que alguns dos meus prefixos S3 não existiam / não tinham objetos)
y2k-shubham
1

Se o controle de versão estiver habilitado no intervalo S3:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
Dan-Dev
fonte