-1

I want to delete one folder and its entire contents in AWS S3 using the PHP-SDK. So the equivalent of rm -rf somepath in a normal file-system.

Let us assume that the folder is located at s3://somename/myfolder/1/1679666007/ and inside that has many files and other folders which also have other files inside.

I am trying this at the moment but without success because it is doing nothing, no errors as well is not deleting the folder with all the contents.

use Aws\S3\S3Client;

       $this>client = new S3Client();// is properly initialised but removed details for the example

        $this->client->deleteObject([
            'Bucket' => $this->config['bucket'],
            'Key' => rtrim($name,'/').'/', // the ending trailing slash is required for deleting directories in S3
        ]);

What is the proper way to do it?

I am using "aws/aws-sdk-php": "^3.191", php 8

I think it should exist some way to do it via API because we can do it in AWS S3 UI as well click delete the folder and confirm.

PS: I know that the concept of folder does not exist in S3 so please let us not try to fight over the terminology but be practical and get the concept done, deleting that path and all its subpaths in the most efficient performant way. Thanks in advance.

Kristi Jorgji
  • 1,154
  • 1
  • 14
  • 39
  • 1
    You need to list all files under that prefix and then delete each of them individually. – luk2302 Mar 24 '23 at 14:03
  • What about the "folder" and the nested folders ? I might have not only files inside that folder but also another folder, which has more folders and files inside – Kristi Jorgji Mar 24 '23 at 14:04
  • S3 does not have a concept of Folders, it only has objects that have keys. Some of those keys might have a common prefix, but that's a presentation issue, not anything S3 knows about. – Anon Coward Mar 24 '23 at 14:11
  • @AnonCoward yes I know that as mentioned in the PS part of the question. Question is how to achieve that because it clearly can be done via the AWS S3 UI and should be a way to do this via API too. Will try two api calls now first to delet matching objects afterward a single one (folder only).. – Kristi Jorgji Mar 24 '23 at 14:12
  • There is no single API call to do this. You must list the objects, and delete them with at least two calls. – Anon Coward Mar 24 '23 at 14:13

2 Answers2

0

There is an example in the SDK Example Code Library that deletes all objects in the bucket and then deletes the bucket, and one of the languages is PHP here. You do have to list everything in the bucket and delete all of the contents first, before you can delete the bucket. The full example can be cloned here.

...
try {
    $contents = $s3client->listObjects([
        'Bucket' => $bucket_name,
    ]);
    echo "The contents of your bucket are: \n";
    foreach ($contents['Contents'] as $content) {
        echo $content['Key'] . "\n";
    }
} catch (Exception $exception) {
    echo "Failed to list objects in $bucket_name with error: " . $exception->getMessage();
    exit("Please fix error with listing objects before continuing.");
}

try {
    $objects = [];
    foreach ($contents['Contents'] as $content) {
        $objects[] = [
            'Key' => $content['Key'],
        ];
    }
    $s3client->deleteObjects([
        'Bucket' => $bucket_name,
        'Key' => $file_name,
        'Delete' => [
            'Objects' => $objects,
        ],
    ]);
    $check = $s3client->listObjects([
        'Bucket' => $bucket_name,
    ]);
    if (count($check) <= 0) {
        throw new Exception("Bucket wasn't empty.");
    }
    echo "Deleted all objects and folders from $bucket_name.\n";
} catch (Exception $exception) {
    echo "Failed to delete $file_name from $bucket_name with error: " . $exception->getMessage();
    exit("Please fix error with object deletion before continuing.");
}

try {
    $s3client->deleteBucket([
        'Bucket' => $bucket_name,
    ]);
    echo "Deleted bucket $bucket_name.\n";
} catch (Exception $exception) {
    echo "Failed to delete $bucket_name with error: " . $exception->getMessage();
    exit("Please fix error with bucket deletion before continuing.");
}
rlhagerm
  • 334
  • 6
  • I don't want to delete one entire bucket but only one entire folder – Kristi Jorgji Mar 24 '23 at 14:21
  • Ah, ok. There really aren't folders, just paths in S3. So you could get the entire list, then filter to the items in that path, then delete all of those items. Once you delete all the items in the path it would be gone. – rlhagerm Mar 24 '23 at 14:55
0

I got it working using this approach

        $this->client->deleteMatchingObjects($this->config['bucket'], $name); // deletes the files
        $this->client->deleteObject([
            'Bucket' => $this->config['bucket'],
            'Key' => rtrim($name,'/').'/', // the ending trailing slash is required for deleting directories in S3
        ]);

I think the only drawback of the above method is that will delete also a file named with same name as the folder if it exists (very unlikely), other than that it is working very good.

Kristi Jorgji
  • 1,154
  • 1
  • 14
  • 39