web-dev-qa-db-fra.com

Comment supprimer des fichiers de manière récurrente d'un compartiment S3

J'ai la structure de dossier suivante dans S3. Existe-t-il un moyen de supprimer récursivement tous les fichiers d'un dossier (par exemple, foo/bar1 or foo or foo/bar2/1 ..)

foo/bar1/1/..
foo/bar1/2/..
foo/bar1/3/..

foo/bar2/1/..
foo/bar2/2/..
foo/bar2/3/..
54
priya

Avec les derniers outils de ligne de commande aws-cli python , supprimer récursivement tous les fichiers d'un dossier dans un compartiment est simplement:

aws s3 rm --recursive s3://your_bucket_name/foo/

Ou supprimez tout ce qui se trouve sous le seau:

aws s3 rm --recursive s3://your_bucket_name

Si vous souhaitez réellement supprimer le compartiment, il existe un raccourci en une étape:

aws s3 rb --force s3://your_bucket_name

qui supprimera récursivement le contenu de ce compartiment, puis le supprimera.

Remarque: le préfixe de protocole s3:// est requis pour que ces commandes fonctionnent.

105
number5

Auparavant, cela nécessitait un appel d'API dédié par clé (fichier), mais a été grandement simplifié par l'introduction de Amazon S3 - Suppression d'objets multiples en décembre 2011:

Amazon S3 nouvelle suppression multi-objet vous donne la possibilité de supprimer jusqu'à 1 000 objets d'un compartiment S3 en une seule requête.

Voir ma réponse à la question connexe supprimer de S3 en utilisant api php en utilisant un caractère générique pour en savoir plus à ce sujet et consulter des exemples respectifs dans PHP (le AWS SDK pour PHP prend en charge ceci depuis version 1.4.8 ).

La plupart des bibliothèques clientes AWS ont entre-temps introduit un support dédié à cette fonctionnalité d’une manière ou d’une autre, par exemple:

Python

Vous pouvez y parvenir avec l'excellente interface boto / AWS/Python qui se présente comme suit (non testé, du haut de ma tête):

import boto
s3 = boto.connect_s3()
bucket = s3.get_bucket("bucketname")
bucketListResultSet = bucket.list(prefix="foo/bar")
result = bucket.delete_keys([key.name for key in bucketListResultSet])

Rubis

Ceci est disponible depuis version 1.24 du AWS SDK for Ruby et les notes de publication fournissent également un exemple:

bucket = AWS::S3.new.buckets['mybucket']

# delete a list of objects by keys, objects are deleted in batches of 1k per
# request.  Accepts strings, AWS::S3::S3Object, AWS::S3::ObectVersion and 
# hashes with :key and :version_id
bucket.objects.delete('key1', 'key2', 'key3', ...)

# delete all of the objects in a bucket (optionally with a common prefix as shown)
bucket.objects.with_prefix('2009/').delete_all

# conditional delete, loads and deletes objects in batches of 1k, only
# deleting those that return true from the block
bucket.objects.delete_if{|object| object.key =~ /\.pdf$/ }

# empty the bucket and then delete the bucket, objects are deleted in batches of 1k
bucket.delete!

Ou:

AWS::S3::Bucket.delete('your_bucket', :force => true)
51
Steffen Opel

Vous pouvez également envisager d'utiliser Amazon S3 Lifecycle pour créer une expiration pour les fichiers avec le préfixe foo/bar1.

Ouvrez la console du navigateur S3 et cliquez sur un compartiment. Cliquez ensuite sur Propriétés, puis sur LifeCycle.

Créez une règle d'expiration pour tous les fichiers avec le préfixe foo/bar1 et définissez la date sur 1 jour depuis la création du fichier.

Enregistrer et tous les fichiers correspondants seront partis dans les 24 heures.

N'oubliez pas de supprimer la règle une fois que vous avez terminé!

Aucun appel d'API, aucune bibliothèque, application ou script tiers.

Je viens de supprimer plusieurs millions de fichiers de cette façon.

Une capture d'écran représentant la fenêtre Lifecycle Rule (remarque: dans cette photo, le préfixe est laissé vide et concerne toutes les clés du compartiment):

enter image description here

39
Ryan

Si vous souhaitez supprimer tous les objets avec le préfixe "foo /" à l’aide de Java AWS SDK 2.0

import Java.util.ArrayList;
import Java.util.Iterator;
import software.Amazon.awssdk.services.s3.S3Client;
import software.Amazon.awssdk.services.s3.model.*;

//...

ListObjectsRequest listObjectsRequest = ListObjectsRequest.builder()
    .bucket(bucketName)
    .prefix("foo/")
    .build()
;
ListObjectsResponse objectsResponse = s3Client.listObjects(listObjectsRequest);

while (true) {
    ArrayList<ObjectIdentifier> objects = new ArrayList<>();

    for (Iterator<?> iterator = objectsResponse.contents().iterator(); iterator.hasNext(); ) {
        S3Object s3Object = (S3Object)iterator.next();
        objects.add(
            ObjectIdentifier.builder()
                .key(s3Object.key())
                .build()
        );
    }

    s3Client.deleteObjects(
        DeleteObjectsRequest.builder()
            .bucket(bucketName)
            .delete(
                Delete.builder()
                    .objects(objects)
                    .build()
            )
            .build()
    );

    if (objectsResponse.isTruncated()) {
        objectsResponse = s3Client.listObjects(listObjectsRequest);
        continue;
    }

    break;
};
2
abguy

Avec le package s3cmd installé sur une machine Linux, vous pouvez le faire

s3cmd rm s3://foo/bar --recursive

2
MichaelZ

Je viens de supprimer tous les fichiers de mon compartiment à l'aide de PowerShell:

Get-S3Object -BucketName YOUR_BUCKET | % { Remove-S3Object -BucketName YOUR_BUCKET -Key $_.Key -Force:$true }
2
velaskec

Je viens de voir qu'Amazon a ajouté une option "Comment vider un seau" au menu de la console AWS:

http://docs.aws.Amazon.com/AmazonS3/latest/UG/DeletingaBucket.html

1
JamesKn

En cas d'utilisation de AWS-SDK pour Ruby V2.

s3.list_objects(bucket: bucket_name, prefix: "foo/").contents.each do |obj|
  next if obj.key == "foo/" 
  resp = s3.delete_object({
    bucket: bucket_name,
    key: obj.key,
  })
end

attention s'il vous plaît, tous les "foo/*" sous seau vont supprimer.

1
Hajime

Je devais faire ce qui suit ...

def delete_bucket
  s3 = init_Amazon_s3
  s3.buckets['BUCKET-NAME'].objects.each do |obj|
    obj.delete
  end
end

def init_Amazon_s3
  config = YAML.load_file("#{Rails.root}/config/s3.yml")
  AWS.config(:access_key_id => config['access_key_id'],:secret_access_key => config['secret_access_key'])
  s3 = AWS::S3.new
end
0
Imdad

La réponse votée manque une étape. Remarque: Le débordement de pile analyse les astérisques, nous utilisons donc le texte "étoile" comme espace réservé dans les exemples ci-dessous. Merci!

Per aws s3 help:

Blockquote Actuellement, l'utilisation de caractères génériques de style UNIX dans un fichier .__ n'est pas prise en charge. arguments du chemin de la commande. Cependant, la plupart des commandes ont --exclude Les paramètres "" et --include "" permettant d'atteindre le résultat souhaité ......... quand il y a plusieurs filtres, la règle est les filtres qui apparaissent plus tard dans la commande prendre la priorité sur les filtres qui apparaissent plus tôt dans la commande. Par exemple, si les paramètres de filtre transmis à la commande étaient --exclude "star" --include "star.txt" Tous les fichiers seront exclus de la commande, à l'exception des fichiers se terminant par avec .txt

aws s3 rm --recursive s3://bucket/ --exclude="star" --include="/folder_path/star" 

Notez qu'il doit y avoir une STAR après le chemin du dossier

0
einarc

Le meilleur moyen consiste à utiliser la règle de cycle de vie pour supprimer le contenu de tout le compartiment. Par programme, vous pouvez utiliser le code suivant (PHP) pour appliquer la règle de cycle de vie.

$expiration = array('Date' => date('U', strtotime('GMT midnight')));
$result = $s3->putBucketLifecycle(array(
            'Bucket' => 'bucket-name',
            'Rules' => array(
                array(
                    'Expiration' => $expiration,
                    'ID' => 'rule-name',
                    'Prefix' => '',
                    'Status' => 'Enabled',
                ),
            ),
        ));

Dans le cas ci-dessus, tous les objets seront supprimés à partir de Date - "Aujourd'hui GMT à minuit". 

Vous pouvez également spécifier les jours comme suit. Mais avec Days, il faudra attendre au moins 24 heures (un jour au minimum) pour commencer à supprimer le contenu du compartiment.

$expiration = array('Days' => 1);
0