How To: Programmatically Delete a Folder from each site

SharePoint

In this post I’ll show you how to write a PowerShell script that will delete a single folder from multiple sites. In this case, there’s a folder called "Error Logs" in the Site Pages document library, as shown here:

image

This folder is generated by some 3rd party tool, which always creates the same folder name in the "Site Pages" Document Library of any site or sub-site. I’d like to simply delete it.

Disclaimer: The method I’m going to show you is just one way to do it and there may be a better way so feel free to write your suggestions in the comments.

So first, let’s just get some constant variables out of the way:

?View Code POWERSHELL
1
2
$url = "http://sharepoint"
$folder = "Error Logs"

$url is my portal URL and all the sites are underneath it. And $folder is the name of the folder I want to delete. The next thing I need to do is loop through each of my Site Collections (an SPSite object), here’s how that looks:

?View Code POWERSHELL
1
2
3
4
5
$sites = Get-SPSite -WebApplication $url | Where-Object {$_.Url -like "$url/sites/*"}
foreach ($site in $sites)
        {
        # Some functions here.
        }

So, I used Get-SPSite to get a list of the Site Collections and also used the | (pipe) symbol to only select sites that had a name like http://sharepoint/sites/

I’m trying to access a Document Library, which is inside a Site (an SPWeb object). So I’ll need to do a loop within a loop to go through every Site, in each Site Collection.

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
$sites = Get-SPSite -WebApplication $url | Where-Object {$_.Url -like "$url/sites/*"}
foreach ($site in $sites)
	{
	$siteid = $site | Select-Object -ExpandProperty Url
	$webs = Get-SPWeb -Site $siteid -Limit ALL
	foreach ($web in $webs)
		{
                # Some more functions here.
                }

What I’m doing here is is getting every Site Collection, selecting its "Url" and assigning it to $siteid. Then I use that to get every Site (SPWeb) in the Site Collection and assign it to $webs. Now I can iterate though all the Sites/SPWebs.

Next, I’ll need to grab the Document Library object, and delete the "Error Logs" folder:

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
$sites = Get-SPSite -WebApplication $url | Where-Object {$_.Url -like "$url/sites/*"}
foreach ($site in $sites)
	{
	$siteid = $site | Select-Object -ExpandProperty Url
	$webs = Get-SPWeb -Site $siteid -Limit ALL
	foreach ($web in $webs)
		{
                $library = $web.Folders["SitePages"]
		$library.SubFolders.Delete($folder)
                }

That’s all. Now, when you run this, it will work – but you’ll notice some errors, perhaps similar to this:

image

The reason for this is that not all of my sites have a Document Library called Site Pages. And even if they do, they may not all have a folder called "Error Logs." So, we need some better logic. We’ll use “If” to create that logic.

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	$webs = Get-SPWeb -Site $siteid -Limit ALL
	foreach ($web in $webs)
		{
		$library = $web.Folders["SitePages"]
		$allcontainers = $library.SubFolders | select Name
		Foreach ($container in $allcontainers)
			{
				If ($container -match $folder)
					{
					$library.SubFolders.Delete($folder)
					Write-Host "Deleted `"$folder`" from $web" -foregroundcolor Red
					}
				else {Write-Host "Finished checking $web." -foregroundcolor DarkGreen}
			}
		}

You’ll see here that I’ve created yet another loop! Now, I’m taking all the folder names from "SitePages" Document Library and looping through each one. I have an "If" statement that checks for a match and if it finds one, then and only then will it try to delete it. Otherwise, we just write a message stating we’ve checked the site.

Here’s the final, full script:

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$url = "http://sharepoint"
$folder = "Error Logs"
 
$sites = Get-SPSite -WebApplication $url | Where-Object {$_.Url -like "$url/sites/*"}
foreach ($site in $sites)
	{
	$siteid = $site | Select-Object -ExpandProperty Url
	$webs = Get-SPWeb -Site $siteid -Limit ALL
	foreach ($web in $webs)
		{
		$library = $web.Folders["SitePages"]
		$allcontainers = $library.SubFolders | select Name
		Foreach ($container in $allcontainers)
			{
				If ($container -match $folder)
					{
					$library.SubFolders.Delete($folder)
					Write-Host "Deleted `"$folder`" from $web" -foregroundcolor Red
					}
				else {Write-Host "Finished checking $web." -foregroundcolor DarkGreen}
			}
		}
	}
Write-Host "Finished checking all sites."

Permissions problems are common when accessing Sites this way. I was a Farm Administrator and had rights over the content database for the Web Application I was working on. With the power of loops, you can take all sorts of actions on every Site in your SharePoint farm.

email
1 comment… add one
  • Chris Feb 22, 2016

    Why is there not just a way to delete ONE folder.

    $site.delete($folder);

    Surely I don’t have to go through this rigmarole to delete one lousy folder, do I?

Leave a Comment

%d bloggers like this: