Backup Documents in SharePoint Using PowerShell

I use SharePoint in my lab at home and recently started organizing all of my personal documents in there as well.  The one thing that always concerns me is the safety of those files living in a lab environment on a Beta/RC product.

So, to ease my nerves, I wrote this simple little script which runs through my web applications and copies the documents down to the filesystem in a similar hierarchical structure. It’s still a work in progress, but I thought I’d share.

DISCLAIMER: This script is not meant for a production environment nor should it be considered an accurate means to backup your data.  Please follow best practices for backup and recovery of your data.  Additionally, this script, nor the use of it, is supported in any way.  Use at your own risk.

SharePoint Backup and Recovery Topics
https://technet.microsoft.com/en-us/library/cc262412.aspx

https://technet.microsoft.com/en-us/library/cc262129.aspx

And here it is….  The script can be run via Scheduled Task, but it has some nifty progress bars if you run it manually in a PS “shell” instance.

param([string]$webApplicationList=(Read-Host "Provide a comma delimited list of web application urls to crawl and backup"), [string]$path=(Read-Host "Specify the root location where to save files"))

cls

Write-Progress -Status "Clearing documents at location: $path" -Activity "Deleting Files"
Get-ChildItem -path $path -recurse | Remove-Item -Recurse -Confirm:$false

Write-Progress -Status "Loading Microsoft.SharePoint" -Activity "Loading Assemblies"
$null = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

Write-Progress -Status "Loading Microsoft.SharePoint.Administration" -Activity "Loading Assemblies"
$null = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Administration")

Write-Progress -Status "Loading System.IO" -Activity "Loading Assemblies"
$null = [System.Reflection.Assembly]::LoadWithPartialName("System.IO")

Write-Progress -Status "Getting reference to local SPFarm object" -Activity "Getting SPFarm"
$farm = [Microsoft.SharePoint.Administration.SPFarm]::Local

#split web application urls into array
$webApplicationUrls = $webApplicationList.Split(',')

$webAppIndex = 1;
foreach($webApplicationUrl in $webApplicationUrls)
{
    $webAppPct = ($webAppIndex / $webApplicationUrls.Length)*100
    Write-Progress -id 1 -Activity "SPWebApplication" -Status "Web Application:" -PercentComplete $webAppPct
    $uri = new-object System.Uri($webApplicationUrl)
    $webApp = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($uri);
    if($webApp -ne $null)
    {
        $webAppName = $webApp.DisplayName
        $path1 = "$path\$webAppName"
        $null = New-Item -Path "$path1" -ItemType "Directory"
        for($s = 1; $s -le $webApp.Sites.Count; $s++)
        {
            $site = $webApp.Sites[$s-1]
            $siteName = $site.RootWeb.Title
            $spct = ($s / $webApp.Sites.Count)*100
            Write-Progress -id 2 -ParentId 1 -Activity "SPSite" -Status "Site Collection: $siteName" -PercentComplete $spct
            for($w = 1; $w -le $site.AllWebs.Count; $w++)
            {
                $web = $site.AllWebs[$w-1]
                $webName = $web.Title
                $wpct = ($w / $site.AllWebs.Count)*100
                Write-Progress -id 3 -ParentId 2 -Activity "SPWeb" -Status "Web: $webName" -PercentComplete $wpct
                $path2 = "$path1\$webName"
                if([System.IO.Directory]::Exists("$path2") -eq $false)
                {
                    $null = New-Item -Path "$path2" -ItemType "Directory"
                }
                for($l = 1; $l -le $web.Lists.Count; $l++)
                {
                    $list = $web.Lists[$l-1]
                    if($list.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary -and $list.RootFolder.ToString().IndexOf("_catalogs") -eq -1 -and $list.Title -ne "Forms")
                    {
                        $listName = $list.Title
                        $lpct = ($l / $web.Lists.Count)*100
                        Write-Progress -id 4 -ParentId 3 -Activity "SPList" -Status "List: $listName" -PercentComplete $lpct
                        $path3 = "$path2\$listName"
                        if([System.IO.Directory]::Exists("$path3") -eq $false)
                        {
                            $null = New-Item -Path "$path3" -ItemType "Directory"
                        }    
                        for($f = 1; $f -le $list.ItemCount; $f++)
                        {
                            $item = $list.Items[$f-1]
                            if($item -ne $null)
                            {
                                $itemName = $item.File.Name;
                                if($itemName -ne "")
                                {
                                    $fpct = ($f / $list.ItemCount)*100
                                    Write-Progress -id 5 -ParentId 4 -Status "SPFile" -Activity "File: $itemName" -PercentComplete ($fpct)
                                    $path4 = "$path3\$itemName"
                                    $fs = [System.IO.File]::Create("$path4");
                                    $bytes = $item.File.OpenBinary();
                                    $fs.Write($bytes, 0, $bytes.Length);
                                    $fs.Close();
                                }
                            }
                            Write-Progress -Status "Writing files..." -Activity "Web: $webName List: $listName" -PercentComplete ($i / $list.ItemCount) -CurrentOperation $itemName
                        }
                    }
                }
                $web.Dispose();
            }
            $site.Dispose();
        }
    }
    $webAppIndex++
}