12

I just started trying out Amazon S3 for hosting my website's images. I'm using the official Amazon AWS PHP SDK library.

Problem: How can I delete all files located in a S3 'folder'?
For example if I have a file named images/2012/photo.jpg, I want to delete all files whose filenames start with images/2012/.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Nyxynyx
  • 61,411
  • 155
  • 482
  • 830

5 Answers5

34

The best way to delete a folder from S3 with all its files is using the API deleteMatchingObjects()

$s3 = S3Client::factory(...);
$s3->deleteMatchingObjects('YOUR_BUCKET_NAME', '/some/dir');

Please consider the comment of @FranciscoCarmona which I report here to give evidence:

Just note one thing. If you have a file named dirXXX.jpg within "some" directory that will remove the file too. So that is not correct. You will have to add a regex. $s3->deleteMatchingObjects('YOUR_BUCKET_NAME', '/some/dir', '/^some/dir//');

Luigi C.
  • 990
  • 12
  • 22
  • Thank you so much luigi. You make my work so easy .. :) – Neeraj Rathod May 14 '16 at 09:37
  • Luigi, One thing wanna ask you , does this API deleteMatchingObjects() gives any success message. – Neeraj Rathod May 14 '16 at 09:40
  • If no Exception is raised, it means success. It can be also useful to check the return value of deleteMatchingObjects() which is an int equals to the number of deleted keys. – Luigi C. May 16 '16 at 07:10
  • 4
    Just note one thing. If you have a file named dirXXX.jpg within "some" directory that will remove the file too. So that is not correct. You will have to add a regex. $s3->deleteMatchingObjects('YOUR_BUCKET_NAME', '/some/dir', '/^some\/dir\//'); – Francisco Carmona Feb 19 '18 at 12:08
  • Good observation. My solution was based on the fact that usually you do not mix files and folders in the same level but files are usually stored in the final level of each hierarchy – Luigi C. Feb 20 '18 at 13:51
  • It worked but it only deletes files and not the actual folders. e.g. if you have a folder `accounts/100/gallery/` and within it you have files.. then doing `$s3->deleteMatchingObjects('YOUR_BUCKET_NAME', '/accounts/100');` would delete all the files but the directories would still remain. – Mubashar Abbas May 07 '18 at 13:58
  • 1
    Be warned! As @FranciscoCarmona said, deleting `/some/dir` will also delete a file named `/some/dir123.jpg`. But it will also delete another directory named `/some/dir2`! – andreas Apr 03 '23 at 16:46
10

S3 does not have "folders" as you would traditionally think of them on a file system (some S3 clients just do a nice job making S3 appear to have folders). Those / are actually part of the file name.

As such, there is no "delete folder" option in the API. You would just need to delete each individual file that has the images/2012/... prefix.

Update:

This can be accomplished via the delete_all_objects method in the Amazon S3 PHP Client. Simply specify "/^images\/2012\//" as the regex prefix in the second argument (the first argument being your bucket name).

nategood
  • 11,807
  • 4
  • 36
  • 44
  • Are there any functions in the S3 library that can select all files with a particular string in their filename? – Nyxynyx Mar 11 '12 at 20:03
  • Yes via the `delete_all_objects` method. You can specify a regular expression to use to delete all files in a bucket that match the expression. Docs and examples here: http://docs.amazonwebservices.com/AWSSDKforPHP/latest/index.html#m=AmazonS3/delete_all_objects – nategood Mar 12 '12 at 01:15
0
$s3 = new Aws\S3\Client([ 'region' => 'us-west-2', 'version' => 'latest' ]); 
$listObjectsParams = ['Bucket' => 'foo', 'Prefix' => 'starts/with/']; 

// Asynchronously delete 
$delete = Aws\S3\BatchDelete::fromListObjects($s3, $listObjectsParams); 

// Force synchronous completion $delete->delete();
$promise = $delete->promise(); 
HackerBoy
  • 1
  • 1
-1

I've tested this and it works 2019-05-28

function Amazon_s3_delete_dir($delPath, $s3, $bucket) {
//the $dir is the path to the directory including the directory
// the directories need to have a / at the end.  
// Clear it just in case it may or may not be there and then add it back in.
$dir = rtrim($dir, "/");
$dir = ltrim($dir, "/");
$dir = $dir . "/";

$response = $s3->getIterator(
        'ListObjects',
        [
            'Bucket' => $bucket,
            'Prefix' => $delPath
        ]
);
//delete each 
foreach ($response as $object) {
    $fileName = $object['Key'];
    $s3->deleteObject([
        'Bucket' => $bucket,
        'Key' => $fileName
    ]);
}//foreach

    return true;
 }//function

Usage:

$delPath = $myDir . $theFolderName . "/";        
Amazon_s3_delete_dir($delPath, $s3, $bucket);
adatadoc
  • 169
  • 1
  • 7
-1

Here is a function that will do what you are looking to do.

/**
*   This function will delete a directory.  It first needs to look up all objects with the specified directory
*   and then delete the objects.
*/
function Amazon_s3_delete_dir($dir){
    $s3 = new AmazonS3();

    //the $dir is the path to the directory including the directory

    // the directories need to have a / at the end.  
    // Clear it just in case it may or may not be there and then add it back in.
            $dir = rtrim($dir, "/");
            $dir = ltrim($dir, "/");
            $dir = $dir . "/";

    //get list of directories
        $response = $s3->get_object_list(YOUR_A3_BUCKET, array(
           'prefix' => $dir
        ));


    //delete each 
        foreach ($response as $v) {
            $s3->delete_object(YOUR_A3_BUCKET, $v);
        }//foreach

    return true;

}//function

Use: if I want to delete the directory foo

Amazon_s3_delete_dir("path/to/directory/foo/");
Jason
  • 2,687
  • 3
  • 29
  • 40