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

87

J'ai la structure de dossiers suivante dans S3. Existe-t-il un moyen de supprimer récursivement tous les fichiers d'un certain 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/..
Priya
la source

Réponses:

164

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

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 le contenu de ce compartiment de manière récursive, puis supprimera le compartiment.

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

numéro 5
la source
2
cela devrait être la réponse. C'est un outil standard (nouveau) puissant, conçu pour des choses comme cette question
Don Cheadle
Cela supprime très bien les fichiers, mais supprime également le seau après la suppression des fichiers. Ai-je manqué quelque chose?
Naveen
1
@Naveen comme je l'ai dit ci-dessus, rmsupprimera uniquement les fichiers mais rb --forcesupprimera les fichiers et le seau.
nombre5
5
l'utilisation --recursivesupprime également le dossier.
ryantuck
1
@Moseleyi je crois que vous ne pouvez pas réellement avoir un dossier vide dans un seau s3
ryantuck
58

Cela nécessitait auparavant un appel d'API dédié par clé (fichier), mais a été considérablement simplifié en raison de l'introduction d' Amazon S3 - Multi-Object Delete en décembre 2011:

La nouvelle suppression multi-objets d' Amazon S3 vous donne la possibilité de supprimer jusqu'à 1000 objets d'un compartiment S3 avec une seule demande.

Voir ma réponse à la question associée supprimer de S3 à l'aide de l'api php en utilisant un caractère générique pour plus d'informations à ce sujet et des exemples respectifs en PHP (le kit AWS SDK pour PHP prend en charge cela depuis la version 1.4.8 ).

La plupart des bibliothèques clientes AWS ont entre-temps introduit une prise en charge dédiée pour cette fonctionnalité d'une manière ou d'une autre, par exemple:

Python

Vous pouvez y parvenir avec l'excellent boto interface Python avec AWS à peu près 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 la version 1.24 du kit SDK AWS pour 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)
Steffen Opel
la source
devrait utiliser la nouvelle aws cliréponse comme @ number5
Don Cheadle
43

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/bar1et définissez la date sur 1 jour depuis la création du fichier.

Enregistrez et tous les fichiers correspondants seront supprimés dans les 24 heures.

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

Pas d'appels d'API, pas de bibliothèques, d'applications ou de scripts tiers.

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

Une capture d'écran montrant la fenêtre Règle du cycle de vie (notez dans cette photo que le préfixe a été laissé vide, affectant toutes les clés du compartiment):

entrez la description de l'image ici

Ryan
la source
4
Excellente idée d'utiliser Lifecycle au lieu d'une commande de suppression.
xis le
Exactement, laissez S3 le faire pour vous.
Ryan
Vous pouvez également l'appliquer à l'ensemble du compartiment, ce qui vous permet de supprimer le compartiment.
Indolering
8

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

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

MichaelZ
la source
1
Selon l'aide, il s'agit de la suppression d'un seul objet s3cmd del s3://BUCKET/OBJECTou de la suppression complète du compartiment s3cmd rb s3://BUCKET. Il n'y a pas s3cmd rm, du moins selon s3cmd --help.
Paul McMurdie
s3cmd rmest dans l'aide à partir de 2019 (comme alias pour del), c'est une excellente réponse. Les awsoutils cli fonctionnent uniquement avec un /préfixe de fin, mais pas avec un préfixe de dossier et de nom de fichier partiel, alors que s3cmd fonctionne dans les deux cas. Cette réponse a besoin de beaucoup plus de votes positifs, j'ai dû faire défiler beaucoup trop loin pour trouver la bonne solution.
David Parks
8

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;
};
abguy
la source
1
Je ne peux pas trouver une démonstration plus révélatrice de ce que les gens n'aiment pas à propos de Java que cette réponse ...
Jivan
3

En cas d'utilisation d'AWS-SKD 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 le compartiment seront supprimés.

Hajime
la source
2

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 }
velaskec
la source
Merci d'avoir posté cette réponse, j'essayais de faire exactement cette chose et j'avais mis -Key "% _. Key" qui ne fonctionne pas.
Scott Gartner
1

La réponse votée à la hausse manque une étape.

Pour l'aide AWS S3:

Actuellement, il n'y a aucune prise en charge pour l'utilisation de caractères génériques de style UNIX dans les arguments de chemin d'une commande. Cependant, la plupart des commandes ont --exclude "<value>"et des --include "<value>" paramètres qui peuvent atteindre le résultat souhaité ......... Lorsqu'il y a plusieurs filtres, la règle est que les filtres qui apparaissent plus tard dans la commande ont priorité sur les filtres qui apparaissent plus tôt dans la commande. Par exemple, si les paramètres de filtre passés à la commande étaient --exclude "*" --include "*.txt"Tous les fichiers seront exclus de la commande à l'exception des fichiers se terminant par .txt

aws s3 rm --recursive s3://bucket/ --exclude="*" --include="/folder_path/*" 
Einarc
la source
0

Le meilleur moyen est d'utiliser la règle de cycle de vie pour supprimer tout le contenu du compartiment. Par programme, vous pouvez utiliser le code suivant (PHP) pour mettre la règle de cycle de vie PUT.

$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 Date de début - "Aujourd'hui GMT minuit".

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

$expiration = array('Days' => 1);
Shriganesh Shintre
la source
0

J'avais besoin de 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
Imdad
la source