How-To #4: Delete Empty Folders in SharePoint Document Libraries Using Power Automate – Updated

Updated 11/24/2023

In this post, I will show you how to delete empty folders in SharePoint Document Libraries using Power Automate. This flow is manually triggered, but it can be created using any other trigger, such as a schedule or an automated trigger from any connector.

Scenario:
Scan a SharePoint Document Library and delete all folders that don’t have content, such as nested folders or files.

Note: this flow uses actions from the SharePoint REST API. Don’t be afraid; you don’t need to be a developer to do this. The post will explain the actions being used 😀.

Solution:
To create the flow, please follow the steps below:

  1. Click on Create on the left menu and then click on Instant Flow.

  2. Enter the Flow name, select the Manually trigger a flow trigger and click on Create.

  3. Once the flow is in Edit mode, click on + New step to add the first action.
  4. Search for SharePoint http and select the Send an HTTP request to SharePoint. I renamed this action to GetFolders.

  5. For the Site Address property, select the desired site and set the Method property to GET. Once that’s done, set the Uri property to _api/web/GetFolderByServerRelativeUrl(‘/sites/YourSiteName/YourDocumentLibraryName’)/Folders. Finally, set the Headers property as follows: set the Key to accept and the Value to application/json;odata=nometadata.

  6. For the next action, add a Filter array (Data Operation). This action will be used to filter the output of the Send an HTTP request to SharePoint action above. First, set the * From value using this expression: body('GetFolders')?['value']. Because there are 2 parameters this action will filter on, you need to edit the filter in advanced mode. To do this, click on Edit in advanced mode and set the filter to this expression: @and(equals(item()?['ItemCount'], 0), not(equals(item()['Name'], 'Forms'))).
    The first part of the filter checks if the item count for each filter is equals to 0 and the second part checks if the folder names are not equal to Forms. Forms is an internal folder that comes out of the box with every document library and cannot be deleted.

  7. For the next action, add an Apply to each, which I renamed to ForEach Folder, and set the * Select an output from previous steps to the Body from the Filter array action. This action will loop through each folder found in the output of the Filter array action above.

  8. For the next and final action, add another Send an HTTP request to SharePoint inside the Apply to each action listed above. Please see step 4 above for instructions. I renamed this action to Delete Folders.
  9. For the Site Address property, select the desired site and set the Method property to DELETE. Once that’s done, set the Uri property to _api/web/GetFolderByServerRelativeUrl(‘/sites/YourSiteName/YourDocumentLibraryName/items(‘ForEach_Folder’)[‘Name’]‘). This part (items('ForEach_Folder')['Name']) is an expression and must be entered from the Expression tab.

  10. Save the flow and run it. If you followed all the instructions as explained above and there are empty folders in the targeted document library, the flow will work as expected 😀.

I hope this blog post has been informative and if you have any questions, please to do not hesitate to reach out. Thank you for reading.

Photo by Steve Johnson on Unsplash

23 thoughts on “How-To #4: Delete Empty Folders in SharePoint Document Libraries Using Power Automate – Updated

  1. When you use _api/lists/getbytitle(‘Documents’)/items?$filter=FSObjType%20eq%201&$select=Id,LinkFilename,Folder/itemCount&$expand=Folder, you get the folders AND the itemcount. with that you can decide if you want to delete or not. the FSObjtype shows only the folders, the Folder/Itemcount shows you the nr of files or folders.

    Like

      1. I get stuck on #6 – body(‘GetFolders’)?[‘value’] returns an expression (not dynamic content), and it says “body”, which is rejected when I try to save. I’d love to figure this out; we have so many empty folders!

        Like

  2. I keep getting an error on the filter array. Likely the same one as Caite Hoover Stevens did. In step number 6, in the From value field I used Dynamic content – Expression and typed in body(‘GetFolders’)?[‘value’]. Upon hitting ok, it added the pink function icon block with the expression in it, not the green Sharepoint icon Value one you have in your example. I then switched to advanced mode and added the next expression, @and(equals(item()?[‘ItemCount’], 0), not(equals(item()[‘Name’], ‘Forms’)) in the field below it.

    The error says “Fix invalid expressions(s) for the input parameters(s) of operation ‘Filter_array’.

    I’m doing this as a scheduled cloud flow on a monthly recurring basis, so I tried a second time using the manual flow as your example showed and still got the same error.

    Like

  3. I was able to recreate and run this Power Automate. It successfully deleted my test empty folder, however when I tried to run it against an existing SharePoint document library the flow fails to delete any empty folder where the folder name begins with “#”. For example afolder named “Empty Folder” deletes without issues, but a folder named “#1234 Empty Folder” does not delete. Any suggestion?

    Like

  4. Fausto,

    I found this workflow on a microsoft forum and just now found this site. I am new to power automate and am trying to piece this together, however, I am running into the same error as Rachel Campbell did. Any ideas on how to remedy this? FYI, I did rename SharePoint HTTP to match the name in the screenshot.

    Like

      1. Hi Scott,

        That means the action didn’t find any folders. If you use Google Chrome or Microsoft Edge, install the extension XML Tree. Then, open a browser window, grab the URL of your SharePoint site, and append the value of the Uri in the screenshot in Step 5: _api/web/GetFolderByServerRelativeUrl(‘/sites/YourSiteName/YourDocumentLibraryName’)/Folders. Replace the YourSiteName and the YourDocumentLibraryName with the respective name for your site and document library. Once loaded, you will see data in XML format, and the XML Tree extension will make it easy for you to read. This is a quick way to test the SharePoint REST API endpoint.

        Like

  5. Coming back to this again – Step #5, I renamed the step to GetFolders.

    But when I get to the first part of Step 6, that’s where I run into problems.

    In the *From field, I click to enter an expression into the popup (using Expression tab, not the Dynamic tab). I’ve tried:

    body(‘GetFolders’)[‘Value’] and body(‘GetFolders’)?[‘Value’]

    I’ve also tried searching for the body expression and working off that, but the suggested syntax doesn’t match the two inputs above. In both cases, it inserts a pink expression: fx body(…) that throws an error when I try to save: “Fixed invalid expression(s) for the input parameter(s) of operation ‘Filter_array’. The diagram above suggests that I should instead get a green expression: value

    I cannot figure out what I’m doing wrong – deleting folders is just out of my reach!

    Like

    1. Hi Caite,

      What may be happening here is that you are enter Value instead of value. If you look at the body output from the GetFolders action, the array name is value. Please try that and let me know.

      Thank you!

      Like

  6. Hi,
    We are in the process of shifting a lot of old fileserver data to Sharepoint. Using a Powershell script tends to hit timeout problems due to the massive amount of empty folders we are clearing. Your PowerAutomate script is a great alternative, thanks. However I’m hitting one problem – the Filter Array keeps stalling with the error BadRequest. The ‘from’ property value in the ‘query’ action inputs is of type ‘String’. The value must be an array.
    I’ve set it as per your guide, above – body(‘GetFolders’)?[‘value’] or adding the value via dynamic content, but I get the same error each time. Any thoughts, please?

    Thanks

    Rich

    Like

    1. The expression for body(‘GetFolders’)?[‘value’] should be an array. What I would do is that I would check the body output from the GetFolders action to see what the payload looks like. Please check that out and let me know. Thanks!

      Like

  7. Thank you for this solution.
    Can you also please shed some light on how to similarly delete a folder with multiple level of subfolders (with another level of subfolders and files within it) ?
    Thank you in advance!!

    Like

  8. I received the following error: {“odata.error”:{“code”:”-1, Microsoft.SharePoint.Client.InvalidClientQueryException”,”message”:{“lang”:”en-US”,”value”:”The type SP.FolderCollection does not support HTTP DELETE method.”}}}. Any advice on how to correct this?

    Like

  9. I am having the same issue as everyone else, but I think the issue is not with the body(‘GetFolders’)?[‘value’]. If I remove the second part of the filter criteria it works.

    @and(equals(item()?[‘ItemCount’],0)) – save successful

    So I knew it was a problem with the second part. I played with this for HOURS trying to figure out where the extra bracket needed to go. I came up with this that works:

    @and(equals(item()?[‘ItemCount’], ‘0’), not(equals(item()?[‘Name’], ‘Forms’)))

    Like

    1. Hello Melissa,

      Thank you for taking the time to test this out and point out the error in the expression used in the Filter array action. I have updated the post to include the additional parentheses at the end of the expression and also updated the screenshot for that action. Thank you so much!

      Like

Leave a reply to Fausto Capellan Jr Cancel reply