title: Amazon S3 delete sub-folder recursively
body: <p>I have a S3 bucket with nested folder and file-structures. I understand that S3 has a flat concept but bear with me as I state my problem clearly. </p>
  
  <p>I'd like to do this:</p>
  
  <pre><code>delete bucket/do-not-delete-folder/delete-this-folder-recursively
  </code></pre>
  
  <p>I've already poured over the S3 docs and followed the answers given on <a href="https://stackoverflow.com/questions/11426560/amazon-s3-boto-how-to-delete-folder">python - Amazon S3 boto - how to delete folder? - Stack Overflow</a>.</p>
  
  <p>I've tried two different solutions and they produce two different outputs, you guessed it right, none of them doing the thing I want it to do. </p>
  
  <p><strong>Function 1:</strong></p>
  
  <p>This deletes the "do-not-delete-folder" and all its contents recursively. I only want it to delete the sub-folder and not the top-level folder. </p>
  
  <p>I call this with the following params:</p>
  
  <pre><code>DeleteAWSBucketObjects(my-bucket, do-not-delete-folder/delete-this-folder/)
  </code></pre>
  
  <p>The function is:</p>
  
  <pre><code>def DeleteAWSBucketObjects(bucketName, prefixStr):
  
      s3 = boto3.resource('s3')
      bucket = s3.Bucket(bucketName)
  
      try:
          client = boto3.client('s3')
          response = client.list_objects_v2(Bucket=bucketName, Prefix=prefixStr)
          if 'Contents' in response:
              for item in response['Contents']:
                  while response['KeyCount'] == 1000:
                      response = client.list_objects_v2(Bucket=bucketName,
                                  StartAfter=response['Contents'][0]['Key'],)
                      for item in response['Contents']:
                          client.delete_object(Bucket=bucketName, Key=item['Key'])
      except ClientError as e:
          error_code = int(e.response['Error']['Code'])
          print ("DeleteAWSBucketObjects : hit an exception")
          print (error_code)
  
      return
  </code></pre>
  
  <p><strong>Function 2:</strong></p>
  
  <p>Taken from the link mentioned above. I call it with the same params as mentioned above. </p>
  
  <p>Strangely enough, this results in an <code>Access-denied</code> error. I'm running it from within the same code-file in Lambda and same AWS accounts, so I'm not sure why one version of the function deletes everything and the other does not have the access to delete anything. </p>
  
  <pre><code>DeleteAWSBucketObjectsV2(my-bucket, do-not-delete-folder/delete-this-folder/)
  </code></pre>
  
  <p>Function:</p>
  
  <pre><code>def DeleteAWSBucketObjectsV2(bucketName, prefixStr):
  
      s3 = boto3.resource('s3')
      bucket = s3.Bucket(bucketName)
      objects_to_delete = s3.meta.client.list_objects(Bucket=bucketName, Prefix=prefixStr)
  
      delete_keys = {'Objects' : []}
      delete_keys['Objects'] = [{'Key' : k} for k in [obj['Key'] for obj in objects_to_delete.get('Contents', [])]]
      for i in delete_key:
          print("delete_key_array !!!")
          print(str(i))
      try:
          s3.meta.client.delete_objects(Bucket="MyBucket", Delete=delete_keys)
      except ClientError as e:
          error_code = int(e.response['Error']['Code'])
          print ("DeleteAWSBucketObjects : hit an exception")
          print (error_code)
  </code></pre>