Sitecore PowerShell Scripts / by Derek Hunziker

Ask any Sitecore developer what their favorite Sitecore module is, and it'll most likely be the Sitecore PowerShell Extensions Module (Sorry SIM, and Sitecore Rocks, but i'm not counting you as modules).

The Sitecore PowerShell module is especially handy when you've been tasked with applying changes to items in bulk. If the changes cannot be made convenienty in Sitecore Rock's, whipping up a quick PowerShell script is usually my go-to solution.

Below are some handy scripts that I've accumulated. I will continue to update this post with new ones as they're created.

Rename Media Library Items

Use Case: You upgraded to Sitecore 7.2+ and fell victim to the change in Media Library URLs. You need to update all media library item names, replacing hyphens with spaces.

cd 'master:/sitecore/media library'
Get-ChildItem -Recurse . | Where-Object { $_.Name -match "-"  } | ForEach-Object { 
    
    $originalName = $_.Name
    $newName = $originalName -Replace "-", " "
    
    Write-Host "Renaming item from " -nonewline;
    Write-Host $originalName -f Yellow -nonewline;
    Write-Host " to " -nonewline;
    Write-Host $newName -f Green;
    
    $_.Editing.BeginEdit()
    $_.Name = $newName;
    $_.Fields["__Display name"].Value = $originalName;
    $_.Editing.EndEdit()
    
    ""
}

Expand Tokens

Use Case: You added a new field to a template, and you would like to utilize a $name token within it's standard values. There are many existing items which will now have '$name' displayed within the field. You would like to expand those tokens across all language versions so that they take on the existing item's name.

Write-Host -Foreground Red "Start work in the context of 'master' database"
cd 'master:/sitecore/content'

Set-HostProperty -ForegroundColor Green

function GetAllLanguageVersions($item) 
{
    Get-Item $item.ProviderPath -Language * -Version *
}

$itemsToProcess = Get-ChildItem -Recurse . | foreach { GetAllLanguageVersions($_) }
$itemsToProcess | ForEach-Object { $_.Fields.ReadAll() }
$itemsToProcess | Expand-Token | Format-Table -Auto -Property Name, ItemPath, @{Expression={$_.Version};Label="Version"}, ID

Add Language Versions

Use Case: You installed the Chinese Language into Sitecore. All new media library uploads will be automatically versioned in the new language, however, your existing media will not contain a version in the new language, resulting in missing images on the Chinese version of the site. You want to add a new Chinese version to all existing media without adding unnecessary versions to newer media which already have the Chinese version.

cd 'master:/sitecore/media library'
Get-ChildItem . -Recurse | Add-ItemLanguage -TargetLanguage "zh-cn" -IfExist Skip

Search for Content Within Specific Language Versions

Use Case: You are in the process of adding a new language to your site. Your authors entered placeholder text within the new language versions while they await translation. To be sure that everything was translated, you want to find any placeholder text within the specific language versions that shouldn't be there.

cd 'master:/sitecore/content'

function FilterItemsToProcess($item) 
{
    Get-Item $item.ProviderPath -Language "zh-CN"
}

$list = [System.Collections.ArrayList]@()
$itemsToProcess = Get-ChildItem -Recurse . | foreach {FilterItemsToProcess($_)}
if($itemsToProcess -ne $null)
{
    
    $itemsToProcess | ForEach-Object { 
        $match = 0;
        foreach($field in $_.Fields) {

            # Only look within Single-line and Rich Text fields
            # In this example, we look for english content within Chinese versions
            
            if($field.Type -eq "Single-Line Text" -or $field.Type -eq "Rich Text") {
                if($field -match "^[a-zA-Z0-9\s~!@#$%\^&\*\(\)_\+\-=\[\]\{\};':,\.\?]+$") {
                    Write-Host "Found: '$field' within a" $field.Type "field on Item:" $_.ID
                    $match = 1;
                }
            }

        }
        if($match -eq 1){
            [void]$list.Add($_)
        }
    }
}

$list | Format-Table -Auto -Property @{Expression={$_.Version};Label="Version"}, Language, ID

Copy content from one field to another with version history

Use Case: You want to migrate content from one field to another, and you want to do it in a way that preserves the content that existed within each version of the item.

cd 'master:/sitecore/content/home/my section'

function GetAllLanguageVersions($item) 
{
    Get-Item $item.ProviderPath -Language * -Version *
}

function ProcessItem($item) 
{
    $body = $item["MyField"]
    if (![string]::IsNullOrEmpty($body)) {
        $item.Editing.BeginEdit()
        $item.Fields["MyNewField"].Value = $body;
        $item.Editing.EndEdit()
    }
}

$itemsToProcess = Get-ChildItem -Recurse . | Where-Object { $_.TemplateName -match "MyTemplate"  } | foreach {GetAllLanguageVersions($_)}
if($itemsToProcess -ne $null)
{
    $itemsToProcess | foreach {ProcessItem($_)}
}

Move items into subfolder directory structure

Use Case: You have a large amount of items in a single directory (such as news articles). You've outgrown this solution and you want to move the items into a series of predefined subfolders.

$newsRoot = Get-Item /sitecore/content/Home/Newsroom
cd 'master:/sitecore/content/Home/Newsroom'

Get-ChildItem -Recurse . | Where-Object { $_.TemplateName -match "NewsArticle"  } | ForEach-Object { 
    $date = $_.Fields["ArticleDate"]
    if(![string]::IsNullOrEmpty($date)) 
    {
        $year = $date.ToString().Substring(0, 4)
        $month = $date.ToString().Substring(4, 2)

        $yearFolder = Get-ChildItem -Recurse $newsRoot.ItemPath | Where-Object { $_.Name -eq $year }
        $monthFolder = Get-ChildItem -Recurse $yearFolder.ItemPath | Where-Object { $_.Name -eq $month }

        Move-Item $_.ItemPath $monthFolder.ItemPath
        Write-Host "Item moved from $_.ItemPath to $monthFolder.ItemPath"
    }
    else
    {
        Write-Host $_.ItemPath
    }
}

Produce A Caching Report for All Renderings

Use Case: You are doing a performance audit, and would like to generate a list of all Renderings that use caching and those that do not. This can be done by inspecting the "Cacheable" option on the rendering definition items.

cd master:/sitecore/layout/renderings

Write-Host -Foreground Green "Get all renderings that have caching enabled"
Get-ChildItem -Recurse . | Where-Object { $_.TemplateName -ne "Rendering Folder" -and $_.Cacheable -eq "1" } | Format-Table -Auto -Property Name, ItemPath, ID
 
Write-Host -Foreground Red "Get all renderings that have caching disabled"
Get-ChildItem -Recurse . | Where-Object { $_.TemplateName -ne "Rendering Folder" -and $_.Cacheable -eq "" } | Format-Table -Auto -Property Name, ItemPath, ID