Publish all files in a document library programatically using Powershell and SharePoint Online

What is a Publishing enabled site?

A SharePoint publishing site is a classic site that’s built using a publishing site template. It’s a site where authoring and publishing are more structured and where content management processes are enforced. Publishing sites are typically used to create enterprise intranets, communication portals, and public websites.

Note: Before you build a classic publishing site, consider building a modern communication site. See Moving from publishing sites to communication sites.

Publishing sites have unique features that streamline the authoring, approving, and publishing processes. These features are enabled automatically when you create a publishing site and include page layouts, column types, web parts, lists, and libraries.

The following code can be used to check-in, publish and approve all files within a list or document library which has the same name across all site collections (in this case the  “Master Page Gallery” which is needed to publish changes made to core design files such as the masterpage file globally  – you can add your own filters to restrict or expand the files that are actually targeted


#Required Parameters
$sUserName = ""
$sPassword = Read-Host -Prompt "Enter your password: " -AsSecureString
$sSiteUrl = ""
# Title of the List/Library to be targeted
$ListName = "Master Page Gallery"

$host.Runspace.ThreadOptions = "ReuseThread"
# Set Transcript file name
$Now = Get-date -UFormat %Y%m%d_%H%M%S
$File = "c:\PublishFilesSPO_$Now.txt"
#Start Transcript
Start-Transcript -path $File | out-null

#Definition of the function that gets the list of site collections in the tenant using CSOM
function Get-SPOTenantSiteCollections

param ($sSiteUrl,$sUserName,$sPassword)
Write-Host "—————————————————————————-" -foregroundcolor Green
Write-Host "Getting the Tenant Site Collections" -foregroundcolor Green
Write-Host "—————————————————————————-" -foregroundcolor Green

#Adding the Client OM Assemblies
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.Online.SharePoint.Client.Tenant.dll"

#SPO Client Object Model Context
$spoCtx = New-Object Microsoft.SharePoint.Client.ClientContext($sSiteUrl)
$spoCredentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($sUsername, $sPassword)
$spoCtx.Credentials = $spoCredentials
$spoTenant= New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($spoCtx)

#We need to iterate through the $spoTenantSiteCollections object to get the information of each individual Site Collection
foreach($spoSiteCollection in $spoTenantSiteCollections){
if ($spoSiteCollection.Url -like "*denenv*"){
#if ($spoSiteCollection.Url -like "*teams*" -or $spoSiteCollection.Url -like "*sites*"){
Write-Host "Url: " $spoSiteCollection.Url " – Template: " $spoSiteCollection.Template " – Owner: " $spoSiteCollection.Owner
$SiteUrl = $spoSiteCollection.Url
Write-Host "/// Values entered for use in script ///" -foregroundcolor cyan
Write-Host "Site: " -foregroundcolor white -nonewline; Write-Host $SiteUrl -foregroundcolor green
Write-Host "List name: " -foregroundcolor white -nonewline; Write-Host $ListName -foregroundcolor green

# Bind to site collection
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($sUsername, $sPassword)
$Context.Credentials = $credentials
# Bind to list
$list = $Context.Web.Lists.GetByTitle($ListName)
# Query for All Items
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = ""
$collListItem = $list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())

# Go through process for all items
foreach ($ListItem in $collListItem){
# Adding spacer
Write-Host " "
Write-Host "/////////////////////////////////////////////////////////////"
Write-Host " "
# Write the Item ID, the FileName and the Modified date for each items which is will be published
Write-Host "Working on file: " -foregroundcolor yellow -nonewline; Write-Host $ListItem.Id, $ListItem["FileLeafRef"], $ListItem["Modified"], $ListItem["FileRef"]

# Un-comment below "if" when you want to add a filter which files will be published
# Fill out the details which files should be skipped. Example will skip all files which where modifed last < 31-jan-2015
if ($ListItem["FileRef"] -notlike "*Team_MWS*"){
Write-Host "Skip file" -foregroundcolor red
#Write-Host $ListItem | Get-Member
# $ListItem["Modified"] -lt "01/31/2015 00:00:00 AM"){
# Write-Host "This item was last modified before January 31st 2015" -foregroundcolor red
# Write-Host "Skip file" -foregroundcolor red
# continue
# }

# Check if file is checked out by checking if the "CheckedOut By" column does not equal empty

if ($ListItem["CheckoutUser"] -ne $null){
$item = $ListItem.ListItemAllFields
Write-Host $item["Title"]
Write-Host "File is checked Out"

if ($ListItem.ListItemAllFields.FieldValues["Title"]){}else{
Write-Host $ListItem.ListItemAllFields.FieldValues["Name"] -ForegroundColor Green
$ListItem.ListItemAllFields.FieldValues["Title"] = $ListItem.ListItemAllFields.FieldValues["Name"];
# Item is not checked out, Check in process is applied
Write-Host "File: " $ListItem["FileLeafRef"] "is checked out." -ForegroundColor Cyan
$listItem.File.CheckIn("Auto check-in by PowerShell script", [Microsoft.SharePoint.Client.CheckinType]::MajorCheckIn)
Write-Host "- File Checked in" -ForegroundColor Green
if ($ListItem["MinorVersion"] -ne $null){
# Publishing the file
Write-Host "Publishing file:" $ListItem["FileLeafRef"] -ForegroundColor Cyan
$listItem.File.Publish("Auto publish by PowerShell script")
Write-Host "- File Published" -ForegroundColor Green

# Check if the file is approved by checking if the "Approval status" column does not equal "0" (= Approved)
if ($List.EnableModeration -eq $true){
# if Content Approval is enabled, the file will be approved
if ($ListItem["_ModerationStatus"] -ne ‘0’){
# File is not approved, approval process is applied
Write-Host "File:" $ListItem["FileLeafRef"] "needs approval" -ForegroundColor Cyan
$listItem.File.Approve("Auto approval by PowerShell script")
Write-Host "- File Approved" -ForegroundColor Green
else {
Write-Host "- File has already been Approved" -ForegroundColor Green
if ($listItem) {
} else { ‘Write-Host "- File already published" -ForegroundColor Green’ }

catch [System.Exception]
write-host -f red $_.Exception.ToString()

Get-SPOTenantSiteCollections -sSiteUrl $sSiteUrl -sUserName $sUserName -sPassword $sPassword