Amazon S3 boto: ¿cómo eliminar la carpeta?

87

Creé una carpeta en s3 llamada "prueba" y presioné "prueba_1.jpg", "prueba_2.jpg" en "prueba".

¿Cómo puedo usar boto para eliminar la carpeta "prueba"?

wade huang
fuente
1
@pyCthon Tecnología incorrecta. Inténtalo de nuevo.
devinbost

Respuestas:

61

No hay carpetas en S3. En cambio, las claves forman un espacio de nombres plano. Sin embargo, una tecla con barras en su nombre se muestra especialmente en algunos programas, incluida la consola de AWS (consulte, por ejemplo, Amazon S3 boto: ¿cómo crear una carpeta? ).

En lugar de eliminar "un directorio", puede (y debe) enumerar los archivos por prefijo y eliminarlos. En esencia:

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

Sin embargo, las otras respuestas logradas en esta página presentan enfoques más eficientes.


Observe que el prefijo solo se busca mediante la búsqueda de cadenas ficticias. Si el prefijo fuera your/directory, es decir, sin la barra inclinada al final, el programa también eliminaría felizmente your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Para obtener más información, consulte S3 boto list keys a veces devuelve la clave de directorio.

Antti Haapala
fuente
1
¿Cómo borrar el directorio? ¿Si este directorio se eliminará automáticamente cuando se eliminen todos los archivos de este directorio?
wade huang
Gracias ... lo he terminado ~
wade huang
@wadehuang - ¿podrías compartir tu código sobre cómo eliminar carpetas?
letsc
Cómo eliminar archivos en la carpeta de s3 que tienen 2 días de antigüedad en python. tengo esto en mi s3 - bucket / 1 / backups / (10 files) need to remove all files that are two days old
艾瑪艾瑪 艾瑪
186

Aquí está la versión 2018 (casi 2019):

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Raz
fuente
22
Esta es, con mucho, la mejor respuesta.
user554481
1
a alguien le puede resultar útil saber que bucket.objects.all (). delete () vacía todo el bucket sin eliminarlo, sin importar cuántos objetos haya (es decir, no se ve afectado, pero el límite de 1000 elementos). Ver: boto3.amazonaws.com/v1/documentation/api/latest/reference/…
fabiog
1
Hola Raz, esto no me está funcionando, simplemente obtengo corchetes vacíos, es decir, []
Soyf
Lamentablemente, esto no es compatible con el sufijo :(
Anum Sheraz
Lo bueno es que esta solución funciona incluso con más de 1000 objetos
Mabyn
45

Siento que ha pasado un tiempo y boto3 tiene algunas formas diferentes de lograr este objetivo. Esto supone que desea eliminar la "carpeta" de prueba y todos sus objetos. Aquí hay una forma:

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)

Esto debería hacer dos solicitudes, una para buscar los objetos en la carpeta, la segunda para eliminar todos los objetos en dicha carpeta.

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

Patricio
fuente
Esta es, con mucho, la solución más rápida.
profundización
2
Esta es la solución más rápida, pero tenga en cuenta que list_objects no puede devolver más de 1000 claves, por lo que debe ejecutar este código varias veces.
lamplave
4
Puede usar paginator si tiene más de 1k objetos; vea mi respuesta a continuación.
dmitrybelyakov
@deepelement, y solo funciona en boto3, no boto
avocado
1
Esto funciona muy bien, y se puede ejecutar desde una lambda Python, poniendo el código anterior en una función lambda_handler: import boto3; def lambda_handler(event, context): '''Code from above'''. Asegúrese de otorgarle permiso a Lambda para eliminar de S3 y extender el tiempo de espera.
Nadir Sidi
21

Puede usar bucket.delete_keys () con una lista de claves (con una gran cantidad de claves, encontré que esto es un orden de magnitud más rápido que usar key.delete).

Algo como esto:

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

Una ligera mejora en la solución de Patrick. Como se puede saber, tanto list_objects()y delete_objects()tienen un límite objetivo de 1000. Esta es la razón por lo que tiene que paginar lista y eliminar en trozos. Esto es bastante universal y puede darle Prefixa paginator.paginate()para borrar los subdirectorios / rutas

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
fuente
2
Y si desea limitar a un "directorio", utilice la Prefixpalabra clave en paginator.paginate()Ver todas las opciones: boto3.readthedocs.io/en/latest/reference/services/…
Chad
1
con el Prefixfiltro sugerido por @Chad , tuve que agregar un if item is not Nonecheque antes de la eliminación (ya que algunos de mis prefijos S3 no existían / ​​no tenían objetos)
y2k-shubham
1

Si el control de versiones está habilitado en el bucket de S3:

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