Aug 15, 2017

PowerShell Script: List Files and Sub-Folders in a SharePoint Document Library

Just want to share to you guys for today, which I hope it will help you out when you need it. Here is the script to list all files and sub-folders in a SharePoint Document Library.

Syntax:
.\SPDocContent.ps1 [[-Credential] <PSCredential>] [-URL] <String> [-DocumentLibrary] <String> [[-BaseFolderPath] <String>] [[-CSVPath] <String>] [<CommonParameters>]



##############################################################################
#.SYNOPSIS
# Gets a list of files, folders and sub-folders in a SharePoint Online Document Library.
#
#.DESCRIPTION
# Gets a list of files, folders and sub-folders in a SharePoint Online Document Library.
#
#.PARAMETER Credential
# The credential to access with SharePoint Online.
#
#.PARAMETER URL
# The URL of the SharePoint site (can be a sub-site or root site).
#
#.PARAMETER Document Library
# The Document Library name to connect to.
#
#.PARAMETER BaseFolderPath
# Start from particular sub-folder (optional).
#
#.PARAMETER CSVPath
# The path of the CSV file to export the result.
#
#.EXAMPLE
# $Crd = Get-Credential
# .\SPDocContent.ps1 -URL "https://rdz.sharepoint.com" -DocumentLibrary "Documents" -CSVPath "D:\Documents.csv"
##############################################################################

[Cmdletbinding()]
param (
	[Parameter(Mandatory = $false)]
    [System.Management.Automation.PSCredential]$Credential = $null,
    [Parameter(Mandatory=$true)]
    [string]$URL,
    [Parameter(Mandatory=$true)]
    [string]$DocumentLibrary,
    [Parameter(Mandatory=$false)]
    [string]$BaseFolderPath,
	[Parameter(Mandatory = $false)]
    [string]$CSVPath = ""
)

Function ListContent(
    [Parameter(Mandatory=$true)]
    [Microsoft.SharePoint.Client.Folder]$BaseFolder,
    [Parameter(Mandatory=$false)]
    [switch]$Recursive = $false,
    [Parameter(Mandatory=$false)]
    [Microsoft.SharePoint.Client.Folder]$RootFolder,
    [Parameter(Mandatory=$false)]
    [int]$Level = 0
)
{
    $ContentInfo = @()

    $RootLevel = $false;
    $ctx.Load($BaseFolder.Folders)
    $ctx.Load($BaseFolder.Files)
    $ctx.Load($BaseFolder.ParentFolder)
    $ctx.ExecuteQuery()

    if ($RootFolder -eq $null) { $RootLevel = $true; $RootFolder = $BaseFolder; }
    $tabsRepeat = New-Object System.String("`t", ($Level + 1))

    if ($BaseFolder.Folders.Count -gt 0)
    {
        Write-Host "$($tabsRepeat)$($BaseFolder.Folders.Count) sub-folders for $($BaseFolder.ServerRelativeUrl.Replace($RootFolder.ServerRelativeUrl + "/", [System.String]::Empty))" -ForegroundColor Yellow
        for ($i = 0; $i -lt $BaseFolder.Folders.Count; $i++)
        {
            $ctx.Load($BaseFolder.Folders[$i])
            $ctx.ExecuteQuery()
            if ($BaseFolder.Folders[$i])
            {
                if (($RootLevel -and $BaseFolder.Folders[$i].Name -ne "Forms") -or -not $RootLevel)
                {
                    Write-Host "$($tabsRepeat)$($BaseFolder.Folders[$i].ServerRelativeUrl.Replace($RootFolder.ServerRelativeUrl + "/", [System.String]::Empty))"
                    $ContentInfo += [pscustomobject]@{
                        RelativePath = "$($BaseFolder.Folders[$i].ServerRelativeUrl.Replace($RootFolder.ServerRelativeUrl + "/", [System.String]::Empty))";
                        Type = "Folder";
                        Name = "$($BaseFolder.Folders[$i].Name)";
                        Level = $Level;
                    };

                    if ($Recursive -eq $true)
                    {
                        $ContentInfo += (ListContent -BaseFolder $BaseFolder.Folders[$i] -RootFolder $RootFolder -Recursive:$Recursive -Level ($Level + 1))
                    }
                }
            }
        }
    }
    if ($BaseFolder.Files.Count -gt 0)
    {
        Write-Host "$($tabsRepeat)$($BaseFolder.Files.Count) sub-files for $($BaseFolder.ServerRelativeUrl.Replace($RootFolder.ServerRelativeUrl + "/", [System.String]::Empty))" -ForegroundColor Yellow
        for ($i = 0; $i -lt $BaseFolder.Files.Count; $i++)
        {
            $ctx.Load($BaseFolder.Files[$i])
            $ctx.ExecuteQuery()
            if ($BaseFolder.Files[$i])
            {
                $ContentInfo += [pscustomobject]@{
                    RelativePath = "$($BaseFolder.Files[$i].ServerRelativeUrl.Replace($RootFolder.ServerRelativeUrl + "/", [System.String]::Empty))";
                    Type = "File";
                    Name = "$($BaseFolder.Files[$i].Name)";
                    Level = $Level;
                };
                Write-Host "$($tabsRepeat)$($BaseFolder.Files[$i].ServerRelativeUrl.Replace($RootFolder.ServerRelativeUrl + "/", [System.String]::Empty))"
            }
        }
    }
    return $ContentInfo;
}

$ContentInfo = @()
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($URL)
Try
{
    if ($Credential)
    {
        if ($Credential.GetType().FullName -eq "Microsoft.SharePoint.Client.SharePointOnlineCredentials")
        {
            $ctx.Credentials = $Credential
        } elseif ($Credential.GetType().FullName -eq "System.Management.Automation.PSCredential")
        {
            $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Credential.Username,$Credential.Password)
        }
    }
    elseif ($PSCrd)
    {
        Write-Host "No credential set, retrieving from `$PSCrd." -ForegroundColor Yellow
        $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($PSCrd.Username,$PSCrd.Password)
    }
    elseif ($SPCrd)
    {
        Write-Host "No credential set, retrieving from `$SPCrd." -ForegroundColor Yellow
        $ctx.Credentials = $SPCrd
    }
    else
    {
        Write-Host "No credential set, none retrieved." -ForegroundColor Red -BackgroundColor Black
        exit
    }

    $Site = $ctx.Site
    $Web = $ctx.Web
    $ctx.Load($Site)
    $ctx.Load($Web)
    $ctx.Load($Web.Lists)
    $ctx.Load($Web.Webs)
    $ctx.ExecuteQuery()

    $DL = $Web.Lists.GetByTitle($DocumentLibrary)
    $ctx.ExecuteQuery()

    $ctx.Load($DL.RootFolder)
    $ctx.ExecuteQuery()

    if ($BaseFolderPath)
    {
        $RootFolderPath = "$($DL.RootFolder.ServerRelativeUrl)/$($BaseFolderPath)"
        $RootFolder = $DL.RootFolder.Folders.GetByUrl($BaseFolderPath)
        $ctx.Load($RootFolder)
        $ctx.ExecuteQuery()
        $ContentInfo += (ListContent -BaseFolder $RootFolder -Recursive)
    }
    else
    {
        $ContentInfo += (ListContent -BaseFolder $DL.RootFolder -Recursive)
    }

    if ($CSVPath)
    {
        if (Test-Path $CSVPath) { Remove-Item $CSVPath }
        $ContentInfo | Export-Csv $CSVPath -NoTypeInformation
    }
}
Catch
{
    Throw
}
Finally
{
    if ($ctx -ne $null) { $ctx.Dispose(); }
}

Note: this script is only meant for SharePoint Online.