powershell_iconInevitably as a SharePoint admin there will be a time where you need to use PowerShell to traverse through an entire structure of content and perform a certain task.  If you haven’t yet, you will sooner or later.  Let’s say that your business becomes self-aware that there is no governance, and decides to fix part of that by implementing a policy that states:

“All document libraries in SharePoint should retain 3 major versions”

The first step is admitting you have a problem (knowing you need governance), so you can check that box and move on to how to implement this.  You have an entire site collection with 100 subsites, all with document libraries that you need to make this change to.  There are existing PowerShell scripts out there that help you enable versioning in all libraries in the entire site collection, like this one.  What I needed to do was slightly different.  Instead of applying to the whole site collection, I needed this to apply from a starting subsite and THEN traverse all of the subsites (webs) and libraries.  The logic is very similar, but instead of getting the site collection root subsite and getting all webs from there, I just get the subsite to start with and go down.  Here is the script:

$topweb = Get-SPWeb http://sharepoint.contoso.com/projects/projectB
$subsites = $topweb.webs
Foreach ($subsite in $subsites) {
    Write-Host "Web = " $subsite
    foreach ($lib in $subsite.Lists) {
        if (($lib.BaseType -eq "DocumentLibrary") -and ($lib.title -eq "Documents")) {
            Write-Host "Updating Library = " $lib
            # Enable Versioning
            $lib.EnableVersioning = $true
            $lib.Update()
        }
    }
    $subsite.Dispose()
}

Script Analysis

Let’s take a look at this script step by step. 

$topweb = Get-SPWeb http://sharepoint.contoso.com/projects/projectB

Normally this would be where you would be getting a connection to the site collection root.  But in our case, we didn’t want this to apply to every subsite in the site collection, just a parent subsite and all its children.  So we juse Get-SPWeb to get a connection to the web object we want as the parent to start with and store this in a variable called topweb.

$subsites = $topweb.webs

.Webs is just a property on a web object, so running this spits out a list of all of the subsites under the parent web we specified earlier (via $topweb) and stores that list in another variable called subsites.  This will be the list of sites that whose libraries we want to check to update.

Foreach ($subsite in $subsites) { Write-Host "Web = " $subsite

Now we’re saying “for each subsite in the list of all subsites”, we’re about to do some actions.  The closing } is towards the end of the script.  Then we write out to the screen the name of the website website we’re checking.

foreach ($lib in $subsite.Lists) {

Now for all the sites we’re checking, we list out all that sites’ libraries with $subsite.Lists, and we use a foreach to say “for each list or library in all the lists on the site”, we’re about to do stuff.

if (($lib.BaseType -eq "DocumentLibrary") -and ($lib.title -eq "Documents")) { Write-Host "Updating Library = " $lib

We only want to make this change on libraries that are named “Documents”, and are actual a document library and not a list.  We can check the .BaseType property of the List object to see if it’s a list, library, etc.  And we can check it’s title by using the .Title property.  We combine those 2 checks into the above if statement.  We also dump out the name of the library to the screen as well via Write-host. 

$lib.EnableVersioning = $true

$lib.Update()

Now we can do actually do what we want to, change the versioning settings.  There’s a property on the library type called .EnableVersioning that is either true or false.  We set this property to true, and then to save this change, we execute the .Update method on the library.  Done!  All this does is enable major versioning.  If you wanted minor versioning, or wanted to set limits, you could add lines that set these properties:

  • EnableMinorVersions (true or false)
  • MajorVersionLimit (number)
  • MajorWithMinorVersionsLimit (number)

For the VersionLimits, instead of true or false, you just set it to numbers.  An example would be:

$lib.MajorWithMinorVersionsLimit = 3

This could of course be greatly extended, but a lot of times, simple is better and this suited my needs.  Also you can do change or set tons of other options besides versioning.  I highly recommend that you check out Phil Child’s blog entry where he outlines how to set and interact with all of the list and document library settings.