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