The Surly Admin

Father, husband, IT Pro, cancer survivor

Exporting Sites in Sharepoint

I think I’ve mentioned this before, but at work we are divesting one of our business units which is requiring us to split up a lot of data.  One of the bigger challenges has been what to do with our Sharepoint site.  At SeraCare we make very extensive use of our Sharepoint server and have a nearly 80gb database!  This made the upgrade from Sharepoint 2003 (not WSS 3.0) to Sharepoint 2010 pretty challenging, let me tell you!  Now I have to pick up over 800 sites from our Intranet and send it over to the IT department of this divested business unit.  Here’s how I plan to do it.

Sharepoint 2010 is all about PowerShell

Luckily, Sharepoint 2010 was made to work with Powershell from the ground up so automating this means I have all the tools already in place, no need to go out to 3rd party software.  At SeraCare we have a couple of challenges when it comes to moving the Sharepoint sites too, that makes a bit more interesting.  First is there are several sites that have to be “cleaned”, which means the divested business unit can have some of the files but not all of them.  So I had to create a staging site and use Export-SPWeb and Import-SPWeb to move the sites that needed cleaning over to the staging site, then give the correct people permissions to start going through the documents and removing what they don’t need.

Using the 2 cmdlets is essentially a 3 step process that requires:

  1. Export the web site to a file
  2. Create a new web site
  3. Import the exported files into the new web site.

Of course, this is Microsoft and nothing is really that easy, is it?  The export command is actually really straight forward:

Export-SPWeb -Identity http://sharepoint/site -Path "E:\exports\site.cmp" -IncludeVersions ALL

You simply specify the URL of the site you want to export and where you want the export files (using the *.CMP extension) and the last parameter is for document libraries that have version control turned on and you want to export all of the past versions.  You can see the Export-SPWeb help for other options for IncludeVersions and the other parameters that are available.

Step two was a little trickier, because when you create the new web site you have to make sure you use the same template for the new site as the original web site was created with.  Here’s a great listing of all of the templates available.  If don’t use the right template the Import-SPWeb will error out and you’ll have to delete the site and re-create it.  Here’s the import cmdlet:

Import-SPWeb -Identity http://NewSharepoint/NewSite -Path E:\Exports\site.cmp

Even simplier for the import, simply designate the site where you want the import to go and the path to where the export files are located.

The Challenge

I did mention that nothing is ever easy, didn’t I?  The challenge for me was it’s not enough to just pick these sites up and put them into export files and send them over to the other IT department.  First, I feel bad about just doing that and letting them try to figure out how to import them back in so I decided to go the next step and actually script a way to import the sites into their sites.  No idea if they’ll use it, but it at least gives them a template to work with.  The other challenge is the QA department wants assurances that everything copied over correctly, which means document counts.  For every library in every site.  I did mention we have well over 800 sites we’re going to be divesting, right?  Getting document counts is pretty easy in the web interface, you just click on the “All Site Content” link in the bottom left of a Sharepoint site and you can see everything, but doing that for 800 sites would be truly daunting.  Clearly this is a place where automation is not only desired, but a necessity!

The first challenge is how do you get a document count on a site?  I began researching this and first ran across this amazing script that uses the .Net libraries to gather all the information on all documents.  Incredible amount of detail, but not really what I was looking for, and I really wanted to use the new Powershell cmdlets but it got me thinking in the right direction.  First I have to get a collection of all the sites and sub-sites for a particular Sharepoint site.  I had done this already to produce a spreadsheet to help document what needs to be moved and what doesn’t.  Time to break that out.  I always preach doing searches as far to the left as possible, but the -Filter function on Get-SPWeb cmdlet is frustratingly limited so I had to break down and pipe the Get-SPWeb results into a Where-Object.

$Site = "http://Sharepoint/Site"
$Webs = Get-SPWeb -Site http://Sharepoint -Filter { $_.Template -like "*" } -Limit ALL | Where { $_.URL -like "$Site*" }

When using the -Filter parameter with Get-SPWeb you must specify the -Site parameter, which gives the cmdlet a baseline to start from.  This must be the root site of your Sharepoint server.  The frustrating part of the -Filter parameter is you can only search on the Template and Title properties so I just picked Template at random.  The -Limit ALL changes the default behavior of the cmdlet to limit the returned values to about 20 to everything.  I pipe all of that into a Where cmdlet and filter on the site I actually care about.

Now $Webs is loaded with our site and all of the sub-sites (if any).  Now we want to start a loop and enumerate all of the different lists–remember that in Sharepoint everything is a list so this particular method will also pull up the other libraries.

The LISTS property on a Sharepoint Web object is actually a collection of list objects, which is perfect for our needs.

ForEach ($Web in $Webs)
{  ForEach ( $List in $Web.Lists )
   {  $Count = $List.Items.Count
   }
}

Now $List will represent each individual list in that particular web site ($Web).  Unfortunately, $List is also a collection of objects so we can’t just use the .Count property on it to get the number of document/items in that list.  But we can use the .Items property and the .Count property from that.

Works perfectly, except that when I checked it against the web page counts it was wrong.  As I like to say, other then the fact that it doesn’t work it looks good.  This is where I started looking at the document library and trying to figure out what happened and this is when I noticed something interesting.  If I went through every folder in this library and counted up all the document files I ended up with the count that the script came up with, which made me think if I added the number of folders up I would get the number the web site was reporting.  And I did!  Great!  So now all we have to do is figure out how to count the number of folder.  To do this I piped $List into Get-Member to see what I got, and interestingly there is a Folders property, so very promising.  I check $List.Folders and got an array with all of the folders in it–I wasn’t entirely sure this had everything because there were some nested folders so visions of having to write a recursion function danced through my head.  But a quick check of $List.Folders.Count (since every array has the .Count property) gave me the exact number I needed to reach the count reported by the web interface.

ForEach ($Web in $Webs)
{  ForEach ( $List in $Web.Lists )
   {  $Count = $List.Items.Count + $List.Folders.Count
   }
}

Ran this against several different folders and got good results every time.  So in my script I load that information and a few other things (site name, document library title, etc) into a PSObject for later reporting and loop through all of the lists and all of the web sites.

So now just use the $Webs collection and export each site to an export folder and we should be good to go, right?  Not quite–and this is one of those nice problems you occassionally run into.  Turns out the Export-SPWeb cmdlet will export not only the site you specify but every sub-site as well!  I could see no parameter to stop this behavior, if you wanted to.  Luckily in this case I don’t want to.  So I don’t need to export within the $Webs loop, I can just export the whole site and it’s sub-sites before the document count loops and that’s it.

Not entirely it, of course.  I needed to add some error checking, and some verbose output if you want it and the comment-based help but that’s usually pretty quick.  I also added a little something to ease importing the site to another site, but you’ll have to wait for the next blog post to see that!

Source code for Get-SPDocumentCount.ps1 – this is a little script to just retrieve the document counts.

Source code for Export-SPSite.ps1 – here’s the code for the export, including document counts.

Advertisements

February 25, 2013 - Posted by | PowerShell | , , , ,

6 Comments »

  1. […] is the follow-up to the Export-Sharepoint Sites post early this […]

    Pingback by Importing Sharepoint Sites « The Surly Admin | February 28, 2013 | Reply

  2. Hi ,

    I tried to use Export-SPWeb & Import -SPWeb but post import it is throwing error that the List does not exists and the subsite is throwing distribution cache error. please help

    Comment by ranjani | June 18, 2013 | Reply

    • Yes, I discovered this too recently. Kills me how often I’ll test something and then a month later it doesn’t work and have to retool. I have a workaround that mostly works and I’ll try to update the post soon too, just been buried at work and going on vacation soon so it’ll be several weeks, most likely 😦

      Comment by Martin9700 | July 8, 2013 | Reply

  3. Hi Martin,

    I’m getting an error here:

    Missing closing ‘)’ in expression.
    At C:\SharePointExport\Export-SPSite.PS1:4 char:5
    + [ <<<< string]$Site,

    Any ideas please?

    Comment by Dave-Departed | November 8, 2013 | Reply

  4. Hi I was trying to export SP Site, around 250 “*.cmp” files were generated, do I have to import all 250 files in new site?

    Comment by kuldeepshige | August 11, 2014 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: