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:
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:
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:
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.
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:
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:
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.
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:
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.